C/Compilatore e precompilatore/Direttive: differenze tra le versioni
m Annullate le modifiche di 2.230.112.119 (discussione), riportata alla versione precedente di Gian BOT Etichetta: Rollback |
Nessun oggetto della modifica Etichetta: Editor wikitesto 2017 |
||
Riga 12: | Riga 12: | ||
==={{IndexItem|direttive #define}}<code>#define</code>=== |
==={{IndexItem|direttive #define}}<code>#define</code>=== |
||
La direttiva <code>#define</code> serve per definire {{IndexItem|macro}}macro. Sintassi: |
La direttiva <code>#define</code> serve per definire {{IndexItem|macro}}macro. Sintassi: |
||
< |
<syntaxhighlight lang="c"> |
||
#define nomemacro testomacro |
#define nomemacro testomacro |
||
</syntaxhighlight> |
|||
</source> |
|||
Il testo può essere una {{IndexItem|costanti}}costante o un'{{IndexItem|espressioni}}espressione, anche parametrizzata: |
Il testo può essere una {{IndexItem|costanti}}costante o un'{{IndexItem|espressioni}}espressione, anche parametrizzata: |
||
< |
<syntaxhighlight lang="c"> |
||
#include <stdio.h> |
#include <stdio.h> |
||
#include <stdlib.h> |
#include <stdlib.h> |
||
Riga 30: | Riga 30: | ||
return 0; |
return 0; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
Abbiamo trattato l'{{IndexItem|operatore ?}}operatore ? [[C/Blocchi_e_funzioni/Blocchi_if_e_switch#L.27operatore_.3F|qui]]. |
Abbiamo trattato l'{{IndexItem|operatore ?}}operatore ? [[C/Blocchi_e_funzioni/Blocchi_if_e_switch#L.27operatore_.3F|qui]]. |
||
Riga 42: | Riga 42: | ||
Esempio: |
Esempio: |
||
< |
<syntaxhighlight lang="c"> |
||
#include <stdio.h> |
#include <stdio.h> |
||
#include <stdlib.h> |
#include <stdlib.h> |
||
Riga 69: | Riga 69: | ||
return 0; |
return 0; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
Tale codice, una volta elaborato dal preprocessore, è equivalente al seguente: |
Tale codice, una volta elaborato dal preprocessore, è equivalente al seguente: |
||
< |
<syntaxhighlight lang="c"> |
||
/*... trascrizione completa dei file stdio.h e stdlib.h...*/ |
/*... trascrizione completa dei file stdio.h e stdlib.h...*/ |
||
Riga 81: | Riga 81: | ||
return 0; |
return 0; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
Si noti che il preprocessore sostituisce ogni occorrenza delle macro con il loro testo equivalente. |
Si noti che il preprocessore sostituisce ogni occorrenza delle macro con il loro testo equivalente. |
||
Riga 88: | Riga 88: | ||
La direttiva <code>#include</code> è molto importante: permette di includere un file C in un altro. La sua sintassi è la seguente: |
La direttiva <code>#include</code> è molto importante: permette di includere un file C in un altro. La sua sintassi è la seguente: |
||
< |
<syntaxhighlight lang="c"> |
||
#include <nomefile.h> |
#include <nomefile.h> |
||
#include "nomefile.h" |
#include "nomefile.h" |
||
</syntaxhighlight> |
|||
</source> |
|||
Qual è la differenza fra parentesi angolari e virgolette? Dipende dal compilatore, ma solitamente con le parentesi angolari il {{IndexItem|linker}}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. |
Qual è la differenza fra parentesi angolari e virgolette? Dipende dal compilatore, ma solitamente con le parentesi angolari il {{IndexItem|linker}}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. |
||
Riga 102: | Riga 102: | ||
La sintassi è: |
La sintassi è: |
||
< |
<syntaxhighlight lang="c"> |
||
#line numerolinea "nomefile" |
#line numerolinea "nomefile" |
||
</syntaxhighlight> |
|||
</source> |
|||
Esempio: |
Esempio: |
||
< |
<syntaxhighlight lang="c"> |
||
#include <stdio.h> |
#include <stdio.h> |
||
#include <stdlib.h> |
#include <stdlib.h> |
||
Riga 118: | Riga 118: | ||
return 0; |
return 0; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
Il file è opzionale. |
Il file è opzionale. |
||
Riga 128: | Riga 128: | ||
La direttiva <code>#undef</code> serve per cancellare delle macro definite in precedenza con <code>#define</code>. Sintassi: |
La direttiva <code>#undef</code> serve per cancellare delle macro definite in precedenza con <code>#define</code>. Sintassi: |
||
< |
<syntaxhighlight lang="c"> |
||
#undef macro |
#undef macro |
||
</syntaxhighlight> |
|||
</source> |
|||
Esempio: |
Esempio: |
||
< |
<syntaxhighlight lang="c"> |
||
#include <stdio.h> |
#include <stdio.h> |
||
#include <stdlib.h> |
#include <stdlib.h> |
||
Riga 144: | Riga 144: | ||
return 0; |
return 0; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
==Operatori== |
==Operatori== |
||
Riga 155: | Riga 155: | ||
Esempio: |
Esempio: |
||
< |
<syntaxhighlight lang="c"> |
||
#include <stdio.h> |
#include <stdio.h> |
||
#include <stdlib.h> |
#include <stdlib.h> |
||
Riga 165: | Riga 165: | ||
return 0; |
return 0; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
===L'operatore {{IndexItem|operatore ##}}<code>##</code>=== |
===L'operatore {{IndexItem|operatore ##}}<code>##</code>=== |
||
Riga 171: | Riga 171: | ||
Questo operatore si chiama ''operatore di concatenamento''. Esempio: |
Questo operatore si chiama ''operatore di concatenamento''. Esempio: |
||
< |
<syntaxhighlight lang="c"> |
||
#include <stdio.h> |
#include <stdio.h> |
||
#include <stdlib.h> |
#include <stdlib.h> |
||
Riga 182: | Riga 182: | ||
return 0; |
return 0; |
||
} |
} |
||
</syntaxhighlight> |
|||
</source> |
|||
Questo programma stamperà il numero 10. |
Questo programma stamperà il numero 10. |
||
Riga 188: | Riga 188: | ||
===L'operatore {{IndexItem|operatore defined}}<code>defined</code>=== |
===L'operatore {{IndexItem|operatore defined}}<code>defined</code>=== |
||
Questo operatore restituisce ''vero'' se la macro che lo segue è definita. |
Questo operatore restituisce ''vero'' se la macro che lo segue è definita. |
||
< |
<syntaxhighlight lang="c"> |
||
#ifdef MIA_MACRO |
#ifdef MIA_MACRO |
||
puts("mio messaggio"); |
puts("mio messaggio"); |
||
Riga 196: | Riga 196: | ||
puts("mio messaggio"); |
puts("mio messaggio"); |
||
#endif |
#endif |
||
</syntaxhighlight> |
|||
</source> |
|||
È utile quando si vogliono usare gli operatori logici o per rimediare alla mancanza di una direttiva <code>#elifdef</code> |
È utile quando si vogliono usare gli operatori logici o per rimediare alla mancanza di una direttiva <code>#elifdef</code> |
||
< |
<syntaxhighlight lang="c"> |
||
#if defined MACRO_A |
#if defined MACRO_A |
||
puts("aaa"); |
puts("aaa"); |
||
Riga 208: | Riga 208: | ||
puts("eee"); |
puts("eee"); |
||
#endif |
#endif |
||
</syntaxhighlight> |
|||
</source> |
|||
==Le macro== |
==Le macro== |
Versione attuale delle 19:37, 28 gen 2021
Il precompilatore può eseguire diverse istruzioni.
Le direttive[modifica]
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
[modifica]
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
[modifica]
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
[modifica]
La direttiva #include
è molto importante: permette di includere un file C in un altro. La sua sintassi è la seguente:
#include <nomefile.h>
#include "nomefile.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
[modifica]
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
[modifica]
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
[modifica]
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[modifica]
Il preprocessore accetta anche degli speciali operatori:
L'operatore #
[modifica]
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 ##
[modifica]
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
[modifica]
Questo operatore restituisce vero se la macro che lo segue è definita.
#ifdef MIA_MACRO
puts("mio messaggio");
#endif
/* Queste tre righe si possono scrivere anche così */
#if defined MIA_MACRO
puts("mio messaggio");
#endif
È utile quando si vogliono usare gli operatori logici o per rimediare alla mancanza di una direttiva #elifdef
#if defined MACRO_A
puts("aaa");
#elif defined MACRO_B
puts("bbb");
#elif defined MACRO_C && defined MACRO_D
puts("ccc");
#else
puts("eee");
#endif
Le macro[modifica]
Il linguaggio C definisce anche delle macro:
__DATE__
[modifica]
La macro __DATE__
contiene la data della compilazione nel formato mese/giorno/anno.
__FILE__
[modifica]
La macro __FILE__
contiene il nome del file correntemente in compilazione. Può essere modificata con la direttiva #line.
__LINE__
[modifica]
La macro __LINE__
contiene il numero della linea correntemente in compilazione. Può essere modificata con la direttiva #line.
__TIME__
[modifica]
La macro __TIME__
contiene l'ora della compilazione nel formato ore:minuti:secondi.
__STDC__
[modifica]
Il contenuto della macro __STDC__
varia da compilatore a compilatore. Solitamente, se essa è definita, il compilatore accetterà soltanto codice C standard.