Perché #define non richiede un punto e virgola?

Stavo scrivendo del codice di test in C. Per errore avevo inserito un ; dopo un #define , che mi ha dato errori. Perché non è necessario un punto e virgola per #define s?

Più specificamente :

Metodo 1: funziona

 const int MAX_STRING = 256; int main(void) { char buffer[MAX_STRING]; } 

Metodo 2: non funziona – errore di compilazione.

 #define MAX_STRING 256; int main(void) { char buffer[MAX_STRING]; } 

Qual è la ragione del diverso comportamento di quei codici? Quelli di entrambi i MAX_STRING non sono costanti?

#define è una direttiva preprocessore , non un’istruzione o dichiarazione come definita dalla grammatica C (entrambi sono obbligatori per terminare con un punto e virgola). Le regole per la syntax di ognuna sono diverse.

 #define MAX_STRING 256; 

si intende:

ogni volta che trovi MAX_STRING durante la pre-elaborazione, sostituiscilo con 256; . Nel tuo caso farà il metodo 2:

 #include  #include  #define MAX_STRING 256; int main(void) { char buffer [256;]; } 

che non è una syntax valida Sostituire

 #define MAX_STRING 256; 

con

 #define MAX_STRING 256 

La differenza tra i due codici è che nel primo metodo si dichiara una costante uguale a 256 ma nel secondo codice si definisce MAX_STRING come 256; nel tuo file sorgente.

La direttiva #define viene utilizzata per definire valori o macro utilizzati dal preprocessore per manipolare il codice sorgente del programma prima che venga compilato. Poiché le definizioni del preprocessore vengono sostituite prima che il compilatore agisca sul codice sorgente, gli errori introdotti da #define sono difficili da tracciare.

La syntax è:

 #define CONST_NAME VALUE 

se c’è un ; alla fine, è considerato come parte di VALUE .

per capire come funzionano esattamente #define , prova a definire:

 #define FOREVER for(;;) ... FOREVER { /perform something forever. } 

Osservazione interessante di John Hascall :

La maggior parte dei compilatori ti darà un modo per vedere l’output dopo la fase del preprocessore, questo può aiutare con problemi di debug come questo.

In gcc può essere fatto con flag -E .

define è una direttiva preprocessore ed è una semplice sostituzione, non è una dichiarazione.

BTW, in sostituzione potrebbe contenere alcuni ; come parte di esso:

 // Ugly as hell, but valid #define END_STATEMENT ; int a = 1 END_STATEMENT // preprocessed to -> int a = 1; 

Entrambe le costanti? No.

Il primo metodo non produce una costante in linguaggio C. Le variabili qualificate Const non si qualificano come costanti in C. Il primo metodo funziona solo perché i compilatori C99 passati supportano array di lunghezza variabile (VLA). Il tuo buffer è un VLA nel primo caso in particolare perché MAX_STRING non è una costante. Prova a dichiarare lo stesso array nell’ambito del file e riceverai un errore, dal momento che gli VLA non sono consentiti nell’ambito del file.

Il secondo metodo può essere usato per assegnare nomi a valori costanti in C, ma devi farlo correttamente. The ; in definizione macro non dovrebbe essere lì. Le macro funzionano attraverso la sostituzione testuale e non si desidera sostituirle ; nella dichiarazione dell’array. Il modo corretto per definire quella macro sarebbe

 #define MAX_STRING 256 

Nel linguaggio C, quando si tratta di definire costanti con nome corretto, si è fondamentalmente limitati a macro ed enumerazioni. Non cercare di usare const “costanti”, a meno che tu non sappia davvero che funzionerà per i tuoi scopi.

La seconda versione non definisce una costante per quanto riguarda la lingua, solo una regola di sostituzione per un blocco di testo. Una volta che il preprocessore ha fatto il suo lavoro, il compilatore vede

char buffer [256;];

che non è sintatticamente valido

La morale della trama: preferisci la const int MAX_STRING = 256; modo che ti aiuti, il compilatore e il debugger.

Perché è così che è stata decisa la syntax per le direttive del precompilatore .

Solo le affermazioni terminano con a ; in c / c ++, #define è una direttiva pre-processore e non un’istruzione .

Questa direttiva per il preprocessore:

 #define MAX_STRING 256; 

dice al preprocessore di sostituire tutti i MAX_STRING con 256; – e con il punto e virgola . Le istruzioni di preprocessore non hanno bisogno di un punto e virgola alla fine. Se ne metti uno, il preprocessore pensa davvero che tu lo intenda con un punto e virgola.

Se sei confuso con #define s per le costanti, const int sarebbe probabilmente più facile da comprendere.

Se vuoi saperne di più su come utilizzare correttamente queste direttive del preprocessore, prova a guardare questo sito web.