Tipo di variabili #define

Se ho:

#define MAXLINE 5000 

Che tipo MAXLINE intende essere? Devo supporre che sia un int ? Posso testarlo in qualche modo?

In generale, come si può determinare il tipo di variabile #define ed?

Non ha tipo. È una semplice sostituzione di testo. Il testo 5000 verrà lasciato cadere ovunque MAXLINE appare come un token.

Per esempio:

 int a = MAXLINE; 

inserirà il valore 5000 in a .

Mentre

 char *MAXLINE2 = "MAXLINE"; 

non risulterà in

 char *50002 = "5000"; 

Quindi, se vuoi il controllo dei caratteri, le macro non sono la strada da percorrere. Dovresti invece dichiarare costanti statiche, in questo modo il controllo del tipo viene eseguito dal compilatore.

Per informazioni sulle differenze tra static , const e #define , ci sono molte fonti, tra cui questa domanda: statico, define e const in C

(Molto!) In generale, il compilatore C eseguirà 3 attività quando viene eseguito:

  1. Esegui un passaggio di preelaborazione sui tuoi file sorgente,

  2. Eseguire un compilatore sui file di origine preelaborati

  3. Esegui un linker sui file object risultanti.

Linee che iniziano con un # , come la linea

 #define MAXLINE 5000 

è gestito dalla fase del preprocessore. (semplicisticamente) Il preprocessore analizzerà un file ed eseguirà sostituzioni di testo per qualsiasi macro rilevata. Non esiste alcun concetto di tipi all’interno del preprocessore.

Supponiamo di avere le seguenti righe nel file sorgente:

 #define MAXLINE 5000 int someVariable = MAXLINE; // line 2 char someString[] = "MAXLINE"; // line 3 

Il preprocessore rileverà la macro MAXLINE sulla riga 2 e eseguirà una sostituzione di testo. Notare che sulla riga 3 "MAXLINE" non viene considerato come una macro poiché è una stringa letterale.

Al termine della fase del preprocessore, la fase di compilazione vedrà solo quanto segue:

 int someVariable = 5000; // line 2 char someString[] = "MAXLINE"; // line 3 

(i commenti sono stati lasciati per chiarezza, ma sono normalmente rimossi dal preprocessore) Probabilmente si può usare un’opzione sul compilatore per poter ispezionare l’output del preprocessore. In gcc l’opzione -E lo farà.

Si noti che mentre il preprocessore non ha alcun concetto di tipo, non vi è alcun motivo per cui non sia ansible includere un tipo nella macro per completezza. per esempio

 #define MAXLINE ((int)5000) 

il compilatore non vede mai quella linea di codice, un preprocessore viene eseguito prima della compilazione effettiva e sostituisce quelle macro con i loro valori letterali, vedi il link sotto per maggiori informazioni

http://www.cplusplus.com/doc/tutorial/preprocessor/

Non ha tipo. È solo un token che il preprocessore inserirà nel codice sorgente prima di passare il codice al compilatore. Puoi fare questa (ridicola) cosa per dichiarare una variabile chiamata x5000 :

 #define APPEND(x,y) x ## y int main() { int APPEND(x,5000); x5000 = 3; } 

Il preprocessore lo trasforma in questo prima di passarlo correttamente al compilatore:

 int main() { int x5000; x5000 = 3; } 

Quindi, solo perché vedi 5000 in una macro, non significa che debba essere numerico in alcun modo.

MAXLINE non è affatto una variabile. In realtà, non è la syntax C. Parte del processo di compilazione esegue un preprocessore prima del compilatore e una delle azioni che il preprocessore esegue è quella di sostituire le istanze dei token MAXLINE nel file sorgente con qualsiasi cosa venga dopo #define MAXLINE (5000 nel codice della domanda).

A parte: un altro modo comune in cui usi il preprocessore nel tuo codice è con la direttiva #include , che il preprocessore semplicemente sostituisce con i contenuti pre-elaborati del file incluso.

Esempio

Diamo un’occhiata ad un esempio del processo di compilazione in azione. Ecco un file, foo.c , che verrà utilizzato negli esempi:

 #define VALUE 4 int main() { const int x = VALUE; return 0; } 

Io uso gcc e cpp ( il preprocessore C ) per gli esempi, ma probabilmente lo si può fare con qualsiasi suite di compilazione, con bandiere diverse, ovviamente.

Compilazione

Per prima cosa, compiliamo foo.c con gcc -o foo.c Quello che è successo? Ha funzionato; ora dovresti avere un eseguibile foo .

Solo pre-elaborazione

Puoi dire a gcc solo il preprocesso e non fare alcuna compilazione. Se si esegue gcc -E foo.c , si otterrà il file preelaborato nello standard out. Ecco cosa produce:

 # 1 "foo.c" # 1 "" # 1 "" # 1 "foo.c" int main() { const int x = 4; return 0; } 

Si noti che la prima riga di main ha sostituito VALUE con 4 .

Forse ti starai chiedendo quali sono le prime quattro linee. Quelli sono chiamati segnapagina e puoi leggerne di più in Preprocessor Output .

Compilazione senza preelaborazione

Per quanto ne so, non puoi saltare la pre-elaborazione in gcc , ma esistono due approcci per dirti che un file è già stato pre-elaborato. Anche se lo fai, rimuoverà le macro presenti nel file perché non sono destinate al consumo del compilatore. Puoi vedere in che cosa lavora il compilatore in questa situazione con gcc -E -fpreprocessed foo.c :

 . . . . int main() { const int x = VALUE; return 0; } 

Nota: inserisco i punti nella parte superiore; fate finta che siano righe vuote (dovevo metterle lì per far sì che quelle linee venissero visualizzate da SO).

Questo file chiaramente non verrà compilato (prova gcc -fpreprocessed foo.c per scoprirlo) perché VALUE è presente nell’origine, ma non è definito ovunque.

Chiamiamo questa macro o preprocessore, che viene usata per sostituire le stringhe del contenuto del file sorgente. Leggi questo: https://en.wikipedia.org/wiki/C_macro

Sì, puoi presumere che sia un int .

Bene, in realtà tutte le altre risposte sono corrette. Non è C, è solo una direttiva che dice al preprocessore di fare alcune sostituzioni testuali, e come tale non ha tipo. Tuttavia, se non si fanno cose strane con esso (come il trucco del preprocessore ##), si userà tipicamente MAXLINE come una sorta di costante, e il preprocessore lo sostituirà con 5000 che è effettivamente una costante esplicita. E le costanti hanno tipo: 5000 è un int . Una costante scritta come un intero decimale, senza suffisso (come U o L), verrà interpretata dal compilatore come int long int , long int o unsigned long int : il primo di questi tipi che si adatta.

Ma questo naturalmente non ha nulla a che fare con il preprecessore. Potresti riscrivere la tua domanda come “qual è il tipo di 5000 ?”, Senza #define .