Preprocessore

In un file di codice C, ogni riga che inizia con il carattere # non fa tecnicamente parte del linguaggio C, ma è invece una direttiva al preprocessore. Infatti, complessivamente, il sistema C è costituito da:

In precedenza è già stata spiegata la direttiva #include. Adesso, si vedranno le altre principali direttive.

Macro

La direttiva define permette di definire delle macro, dei frammenti di codice sorgente riutilizzabili associati a dei nomi.

Una macro senza parametri viene definita con la sintassi

#define nome testo_di_sostituzione

dove nome è un identificatore e testo_di_sostituzione è un qualunque frammento di testo. L’effetto di questa direttiva è che, a partire dal punto del codice in cui essa compare, il preprocessore sostituisce letteralmente ogni occorrenza dell’identificatore nome con il *testo_di_sostituzione.* E’ importante sottolineare che questa sostituzione avviene in modo letterale, praticamente senza considerare le regole del linguaggio C — di fatto, corrisponde all’operazione “search and replace” di un editor di testo. Si vedrà a breve che ciò ha importanti conseguenze su come le macro devono essere definite e usate.

E’ anche possibile definire macro con parametri, tramite la sintassi

#define nome(parametri_formali) testo_di_sostituzione

dove parametri_formali è una lista di zero o più identificatori, separati da virgole, che costituiscono i parametri formali della macro. Tra il nome della macro e la parentesi della lista dei parametri formali non devono esserci spazi, altrimenti la direttiva verrebbe interpretata come la definizione di una macro senza parametri.

Una macro con parametri viene utilizzata con la sintassi

nome(parametri_attuali)

dove parametri_attuali è una lista di frammenti di codice arbitrari, separati da virgole, che devono essere tanti quanti sono i parametri formali della macro. A partire dal punto in cui la macro è definita, il preprocessore sostituisce ogni occorrenza di questa sintassi con il testo_di_sostituzione, nel quale eventuali occorrenze dei parametri formali vengono a loro volta sostituite con i corrispondenti parametri attuali.

Esempio

Si consideri un file sorgente C contenente il seguente codice

#define DIM_BUFFER 100
#define SCAMBIA(X, Y, T) T = X; X = Y; Y = T

int A[DIM_BUFFER];

int main(int argc, const char *argv[]) {
	int a = 1;
	int b = 2;
	int temp;
	SCAMBIA(a, b, temp);
	// ...
}