direttiva #define (C/C++)
Il #define crea una macro, ovvero l'associazione di un identificatore o un identificatore con parametri con una stringa di token. Dopo che la macro è stata definita, il compilatore può sostituire la stringa di token per ogni occorrenza dell'identificatore presente nel file di origine.
Sintassi
#define identificatore token-string opt
identificatore #define ( identificatoreopt, ... , consenso esplicito dell'identificatore ) per la stringadi token
Osservazioni:
La direttiva #define fa sì che il compilatore sostituirà la stringa del token per ogni occorrenza dell'identificatore nel file di origine. L'identificatore viene sostituito solo quando forma un token. Ovvero, l'identificatore non viene sostituito se viene visualizzato in un commento, in una stringa o come parte di un identificatore più lungo. Per altre informazioni, vedere Token.
L'argomento token-string è costituito da una serie di token, ad esempio parole chiave, costanti o istruzioni complete. Uno o più caratteri di spazio vuoto devono separare la stringa di token dall'identificatore. Questo spazio vuoto non è considerato parte del testo sostituito; né viene considerato alcuno spazio vuoto dopo l'ultimo token del testo.
Un #define
oggetto senza una stringa di token rimuove le occorrenze dell'identificatore dal file di origine. L'identificatore rimane definito e può essere testato usando le #if defined
direttive e #ifdef
.
La seconda forma di sintassi definisce una macro simile a una funzione con parametri. Questa forma accetta un elenco facoltativo di parametri che devono essere visualizzati tra parentesi. Dopo aver definito la macro, ogni occorrenza successiva di identifier( identifieropt, ..., identifieropt ) viene sostituita con una versione dell'argomento token-string con argomenti effettivi sostituiti per i parametri formali.
I nomi dei parametri formali vengono visualizzati nella stringa del token per contrassegnare le posizioni in cui vengono sostituiti i valori effettivi. Ogni nome di parametro può essere visualizzato più volte nella stringa di token e i nomi possono essere visualizzati in qualsiasi ordine. Il numero degli argomenti nella chiamata deve corrispondere al numero di parametri nella definizione della macro. Il libero utilizzo delle parentesi garantisce che gli argomenti effettivi complessi vengano interpretati correttamente.
I parametri formali nell'elenco sono separati da virgole. Ogni nome nell'elenco deve essere univoco e l'elenco deve essere racchiuso tra parentesi. Nessuna spazi può separare l'identificatore e le parentesi di apertura. Usare la concatenazione di riga, ovvero posizionare una barra rovesciata (\
) immediatamente prima del carattere di nuova riga, per direttive lunghe su più righe di origine. L'ambito di un nome di parametro formale si estende alla nuova riga che termina token-string.
Se una macro è stata definita nella seconda forma di sintassi, le successive istanze testuali seguite da un elenco di argomenti indicano una chiamata di macro. Gli argomenti effettivi che seguono un'istanza di identificatore nel file di origine vengono confrontati con i parametri formali corrispondenti nella definizione della macro. Ogni parametro formale nella stringa di token non preceduto da un operatore di stringing (#
), di charizing (#@
) o token-incolla (##
) o non seguito da un ##
operatore, viene sostituito dall'argomento effettivo corrispondente. Eventuali macro presenti nell'argomento effettivo vengono espanse prima che la direttiva sostituisca il parametro formale. Gli operatori sono descritti in Operatori del preprocessore.
Gli esempi seguenti di macro con argomenti illustrano la seconda forma della sintassi #define:
// Macro to define cursor lines
#define CURSOR(top, bottom) (((top) << 8) | (bottom))
// Macro to get a random integer with a specified range
#define getrandom(min, max) \
((rand()%(int)(((max) + 1)-(min)))+ (min))
Gli argomenti con effetti collaterali talvolta determinano la restituzione di risultati imprevisti da parte delle macro. Un parametro formale specificato può essere visualizzato più di una volta nella stringa di token. Se tale parametro formale è sostituito da un'espressione con effetti collaterali, l'espressione, con i relativi effetti collaterali, può essere valutata più volte. (Vedere gli esempi in Operatore Token-Incollaggio (##)).
La direttiva #undef
causa la dimenticanza della definizione del preprocessore di un identificatore. Per altre informazioni, vedere Direttiva #undef .
Se il nome della macro in fase di definizione si verifica in una stringa di token (anche in seguito a un'altra espansione di macro), non viene espanso.
Un secondo #define per una macro con lo stesso nome genera un avviso a meno che la seconda sequenza di token non sia identica alla prima.
Sezione specifica Microsoft
Microsoft C/C++ consente di ridefinire una macro se la nuova definizione è sintatticamente identica alla definizione originale. In altre parole, due definizioni possono avere nomi di parametri diversi. Questo comportamento è diverso da ANSI C, che richiede che le due definizioni siano lessicalmente identiche.
Ad esempio, le due macro seguenti sono identiche a eccezione dei nomi del parametro. ANSI C non consente una ridefinizione di questo tipo, ma Microsoft C/C++ lo compila senza errori.
#define multiply( f1, f2 ) ( f1 * f2 )
#define multiply( a1, a2 ) ( a1 * a2 )
D'altro canto, le due macro seguenti non sono identiche e genereranno un avviso in Microsoft C/C++.
#define multiply( f1, f2 ) ( f1 * f2 )
#define multiply( a1, a2 ) ( b1 * b2 )
Fine sezione specifica Microsoft
Questo esempio illustra la direttiva #define :
#define WIDTH 80
#define LENGTH ( WIDTH + 10 )
La prima istruzione definisce l'identificatore WIDTH
come costante Integer 80 e definisce LENGTH
in termini di WIDTH
come costante Integer 10. Ogni occorrenza di LENGTH
viene sostituita da (WIDTH + 10
). Ogni occorrenza di WIDTH + 10
viene a sua volta sostituita dall'espressione (80 + 10
). Le parentesi intorno a WIDTH + 10
sono importanti in quanto controllano l'interpretazione nelle istruzioni simili alle seguenti:
var = LENGTH * 20;
Dopo la fase di pre-elaborazione l'istruzione diventa:
var = ( 80 + 10 ) * 20;
che restituisce 1800. Senza parentesi, il risultato è:
var = 80 + 10 * 20;
che restituisce 280.
Sezione specifica Microsoft
La definizione di macro e costanti con l'opzione del compilatore /D ha lo stesso effetto dell'uso di una direttiva di pre-elaborazione #define all'inizio del file. È possibile definire fino a 30 macro utilizzando l'opzione /D.
Fine sezione specifica Microsoft