C/Compilatore e precompilatore/Direttive: differenze tra le versioni
Nessun oggetto della modifica |
|||
Riga 33: | Riga 33: | ||
==={{IndexItem|direttive #if, #else, #elif ed #endif}}<tt>#if, #else, #elif ed #endif</tt>=== |
==={{IndexItem|direttive #if, #else, #elif ed #endif}}<tt>#if, #else, #elif ed #endif</tt>=== |
||
Queste direttive servono per la {{IndexItem|compilazione condizionale}}''compilazione condizionale''. Il loro uso è del tutto analogo a quello dell'[[Linguaggio_C/Blocchi_e_funzioni/Blocchi_if_e_switch|istruzione <tt>if</tt>]], ma con una sostanziale differenza: mentre in una normale istruzione <tt>if</tt> la condizione viene valutata a tempo di esecuzione per decidere quale gruppo di istruzioni eseguire, la direttiva #if seleziona a tempo di compilazione quale gruppo di istruzioni debba essere compilato, mentre le istruzioni scartate vengono completamente rimosse e, ai fini del codice eseguibile prodotto, è come non fossero esistite. |
|||
Queste direttive servono per la {{IndexItem|compilazione condizionale}}''compilazione condizionale''. |
|||
Come conseguenza immediata, le espressioni lecite in una direttiva #if sono solo ed esclusivamente quelle valutabili interamente a tempo di compilazione. |
|||
Una forma particolare di direttiva #if è la #ifdef e la sua corrispondente negata #ifndef, che restituiscono un valore di verità rispettivamente vero e falso se la macro fornita come parametro è stata precedentemente definita. |
|||
Esempio: |
Esempio: |
||
Riga 45: | Riga 49: | ||
#define EXPR(a) (a)==6 ? 6 : 0 |
#define EXPR(a) (a)==6 ? 6 : 0 |
||
#ifdef NUM // vera: NUM è stato precedentemente definito |
|||
#ifdef NUM |
|||
#if NUM==10 |
#if NUM==10 // vera |
||
printf("NUM è uguale a 10.\n"); |
printf("NUM è uguale a 10.\n"); |
||
#if EXPR(6) // vera: per un valore pari a 6 del parametro, l'espressione restituisce 6 |
|||
#if EXPR(6) |
|||
printf("EXPR ha dato un risultato! %d\n", EXPR(6)); |
printf("EXPR ha dato un risultato! %d\n", EXPR(6)); |
||
#else |
#else |
||
printf("EXPR non ha dato alcun risultato!\n"); |
printf("EXPR non ha dato alcun risultato!\n"); |
||
#endif |
#endif |
||
#elif NUM<10 |
#elif NUM<10 // falsa |
||
printf("NUM è minore di 10: %d\n", NUM); |
printf("NUM è minore di 10: %d\n", NUM); |
||
#else |
#else |
||
Riga 59: | Riga 63: | ||
#endif |
#endif |
||
#else |
#else |
||
printf("NUM non è definito.\n" |
printf("NUM non è definito.\n"); |
||
#endif |
#endif |
||
return 0; |
return 0; |
||
} |
} |
||
</pre> |
</pre> |
||
Tale codice, una volta elaborato dal preprocessore, è equivalente al seguente: |
|||
<pre> |
|||
/*... trascrizione completa dei file stdio.h e stdlib.h...*/ |
|||
int main(void) |
|||
{ |
|||
printf("NUM è uguale a 10.\n"); |
|||
printf("EXPR ha dato un risultato! %d\n", (6)==6 ? 6 : 0); |
|||
return 0; |
|||
} |
|||
</pre> |
|||
Si noti che il preprocessore sostituisce ogni occorrenza delle macro con il loro testo equivalente. |
|||
==={{IndexItem|direttive #include}}<tt>#include</tt>=== |
==={{IndexItem|direttive #include}}<tt>#include</tt>=== |
Versione delle 06:50, 5 nov 2006
Template:Linguaggio C Il precompilatore può eseguire diverse istruzioni.
Le direttive
Le direttive sono delle istruzioni al precompilatore e dipendono dal compilatore stesso, per cui è consigliabile consultarne la documentazione.
Le direttive non finiscono con il punto e virgola ma con la fin di riga.
Ecco le direttive:
#define
La direttiva #define serve per definire macro. Sintassi:
#define nomemacro testomacro
Il testo può essere una costante o un'espressione, anche parametrizzata:
#include <stdio.h> #include <stdlib.h> int main(void) { #define NUM 10 #define EXPR(a) (a)==6 ? 6 : 0 printf("%d\n", NUM); printf("%d\n", EXPR(7)); return 0; }
Abbiamo trattato l'operatore ? qui.
#if, #else, #elif ed #endif
Queste direttive servono per la compilazione condizionale. Il loro uso è del tutto analogo a quello dell'istruzione if, ma con una sostanziale differenza: mentre in una normale istruzione if la condizione viene valutata a tempo di esecuzione per decidere quale gruppo di istruzioni eseguire, la direttiva #if seleziona a tempo di compilazione quale gruppo di istruzioni debba essere compilato, mentre le istruzioni scartate vengono completamente rimosse e, ai fini del codice eseguibile prodotto, è come non fossero esistite.
Come conseguenza immediata, le espressioni lecite in una direttiva #if sono solo ed esclusivamente quelle valutabili interamente a tempo di compilazione.
Una forma particolare di direttiva #if è la #ifdef e la sua corrispondente negata #ifndef, che restituiscono un valore di verità rispettivamente vero e falso se la macro fornita come parametro è stata precedentemente definita.
Esempio:
#include <stdio.h> #include <stdlib.h> int main(void) { #define NUM 10 #define EXPR(a) (a)==6 ? 6 : 0 #ifdef NUM // vera: NUM è stato precedentemente definito #if NUM==10 // vera printf("NUM è uguale a 10.\n"); #if EXPR(6) // vera: per un valore pari a 6 del parametro, l'espressione restituisce 6 printf("EXPR ha dato un risultato! %d\n", EXPR(6)); #else printf("EXPR non ha dato alcun risultato!\n"); #endif #elif NUM<10 // falsa printf("NUM è minore di 10: %d\n", NUM); #else printf("NUM è maggiore di 10: %d\n", NUM); #endif #else printf("NUM non è definito.\n"); #endif return 0; }
Tale codice, una volta elaborato dal preprocessore, è equivalente al seguente:
/*... trascrizione completa dei file stdio.h e stdlib.h...*/ int main(void) { printf("NUM è uguale a 10.\n"); printf("EXPR ha dato un risultato! %d\n", (6)==6 ? 6 : 0); return 0; }
Si noti che il preprocessore sostituisce ogni occorrenza delle macro con il loro testo equivalente.
#include
La direttiva #include è molto importante: permette di includere un file C in un altro. La sua sintassi è la seguente:
#include <file.h> #include "file.h"
Qual è la differenza fra parentesi angolari e virgolette? Dipende dal compilatore, ma solitamente con le parentesi angolari il linker cerca nelle directory della libreria standard, mentre con le virgolette si cerca il file prima all'interno della directory corrente e poi all'interno delle directory della libreria standard.
#line
La direttiva #line permette di alterare il contenuto delle macro __LINE__ e __FILE__. Essa non salta ad un altro punto del programma; modifica semplicemente queste macro.
La sintassi è:
#line numerolinea "nomefile"
Esempio:
#include <stdio.h> #include <stdlib.h> #line 70 "prova.c" int main(void) //linea 71 { //Linea 72 printf("Linea: %d; File: %s\n", __LINE__, __FILE__); //Linea 73 return 0; }
Il file è opzionale.
#pragma
La direttiva #pragma serve per inviare particolari istruzioni al compilatore. Le opzioni disponibili variano da compilatore a compilatore, per cui è consigliabile consultarne la documentazione.
#undef
La direttiva #undef serve per cancellare delle macro definite in precedenza con #define. Sintassi:
#undef macro
Esempio:
#include <stdio.h> #include <stdlib.h> int main(void) { #define NUM 10 printf("NUM: %d\n", NUM); #undef NUM return 0; }
Operatori
Il preprocessore accetta anche degli speciali operatori:
L'operatore #
Questo operatore serve per trasformare una sequenza di caratteri in stringa all'interno di una macro.
Esempio:
- include <stdio.h>
- include <stdlib.h>
int main(void) {
- define str(s) # s
printf(str(Il C mi piace molto.));
return 0;
}
L'operatore ##
Questo operatore si chiama operatore di concatenamento. Esempio:
#include <stdio.h> #include <stdlib.h> int main(void) { #define cat(x,y) x ## y int cd=10; printf("%d\n", cat(c,d)); return 0; }
Questo programma stamperà il numero 10.
L'operatore defined
Le macro
Il linguaggio C definisce anche delle macro:
__DATE__
La macro __DATE__ contiene la data della compilazione nel formato mese/giorno/anno.
__FILE__
La macro __FILE__ contiene il nome del file correntemente in compilazione. Può essere modificata con la direttiva #line.
__LINE__
La macro __LINE__ contiene il numero della linea correntemente in compilazione. Può essere modificata con la direttiva #line.
__TIME__
La macro __TIME__ contiene l'ora della compilazione nel formato ore:minuti:secondi.
__STDC__
Il contenuto della macro __STDC__ varia da compilatore a compilatore. Solitamente, se essa è definita, il compilatore accetterà soltanto codice C standard.