C/Compilatore e precompilatore/Direttive: differenze tra le versioni

Wikibooks, manuali e libri di testo liberi.
Contenuto cancellato Contenuto aggiunto
m migrazione automatica di 4 collegamenti interwiki a Wikidata, d:q856846
Gian BOT (discussione | contributi)
m sostituzione tag obsoleti
Riga 10: Riga 10:
Ecco le direttive:
Ecco le direttive:


==={{IndexItem|direttive #define}}<tt>#define</tt>===
==={{IndexItem|direttive #define}}<code>#define</code>===
La direttiva <tt>#define</tt> serve per definire {{IndexItem|macro}}macro. Sintassi:
La direttiva <code>#define</code> serve per definire {{IndexItem|macro}}macro. Sintassi:
<source lang="c">
<source lang="c">
#define nomemacro testomacro
#define nomemacro testomacro
Riga 33: Riga 33:
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]].


==={{IndexItem|direttive #if, #else, #elif ed #endif}}<tt>#if, #else, #elif ed #endif</tt>===
==={{IndexItem|direttive #if, #else, #elif ed #endif}}<code>#if, #else, #elif ed #endif</code>===


Queste direttive servono per la {{IndexItem|compilazione condizionale}}''compilazione condizionale''. Il loro uso è del tutto analogo a quello dell'[[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''. Il loro uso è del tutto analogo a quello dell'[[C/Blocchi_e_funzioni/Blocchi_if_e_switch|istruzione <code>if</code>]], ma con una sostanziale differenza: mentre in una normale istruzione <code>if</code> 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.
Come conseguenza immediata, le espressioni lecite in una direttiva #if sono solo ed esclusivamente quelle valutabili interamente a tempo di compilazione.
Riga 85: Riga 85:
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.


==={{IndexItem|direttive #include}}<tt>#include</tt>===
==={{IndexItem|direttive #include}}<code>#include</code>===
La direttiva <tt>#include</tt> è 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:


<source lang="c">
<source lang="c">
Riga 95: Riga 95:
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.


==={{IndexItem|direttive #line}}<tt>#line</tt>===
==={{IndexItem|direttive #line}}<code>#line</code>===


La direttiva <tt>#line</tt> permette di alterare il contenuto delle [[#Macro|macro]] [[#__LINE__|__LINE__]] e [[#__FILE__|__FILE__]].
La direttiva <code>#line</code> permette di alterare il contenuto delle [[#Macro|macro]] [[#__LINE__|__LINE__]] e [[#__FILE__|__FILE__]].
Essa non salta ad un altro punto del programma; modifica semplicemente queste macro.
Essa non salta ad un altro punto del programma; modifica semplicemente queste macro.


Riga 122: Riga 122:
Il file è opzionale.
Il file è opzionale.


==={{IndexItem|direttive #pragma}}<tt>#pragma</tt>===
==={{IndexItem|direttive #pragma}}<code>#pragma</code>===
La direttiva <tt>#pragma</tt> serve per inviare particolari istruzioni al compilatore. Le opzioni disponibili variano da compilatore a compilatore, per cui è consigliabile consultarne la documentazione.
La direttiva <code>#pragma</code> serve per inviare particolari istruzioni al compilatore. Le opzioni disponibili variano da compilatore a compilatore, per cui è consigliabile consultarne la documentazione.


==={{IndexItem|direttive #undef}}<tt>#undef</tt>===
==={{IndexItem|direttive #undef}}<code>#undef</code>===
La direttiva <tt>#undef</tt> serve per cancellare delle macro definite in precedenza con <tt>#define</tt>. Sintassi:
La direttiva <code>#undef</code> serve per cancellare delle macro definite in precedenza con <code>#define</code>. Sintassi:


<source lang="c">
<source lang="c">
Riga 149: Riga 149:
Il preprocessore accetta anche degli speciali operatori:
Il preprocessore accetta anche degli speciali operatori:


===L'operatore {{IndexItem|operatore #}}<tt>#</tt>===
===L'operatore {{IndexItem|operatore #}}<code>#</code>===


Questo operatore serve per trasformare una sequenza di caratteri in stringa all'interno di una macro.
Questo operatore serve per trasformare una sequenza di caratteri in stringa all'interno di una macro.
Riga 167: Riga 167:
</source>
</source>


===L'operatore {{IndexItem|operatore ##}}<tt>##</tt>===
===L'operatore {{IndexItem|operatore ##}}<code>##</code>===


Questo operatore si chiama ''operatore di concatenamento''. Esempio:
Questo operatore si chiama ''operatore di concatenamento''. Esempio:
Riga 186: Riga 186:
Questo programma stamperà il numero 10.
Questo programma stamperà il numero 10.


===L'operatore {{IndexItem|operatore defined}}<tt>defined</tt>===
===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.
<source lang="c">
<source lang="c">
Riga 197: Riga 197:
#endif
#endif
</source>
</source>
È utile quando si vogliono usare gli operatori logici o per rimediare alla mancanza di una direttiva <tt>#elifdef</tt>
È utile quando si vogliono usare gli operatori logici o per rimediare alla mancanza di una direttiva <code>#elifdef</code>
<source lang="c">
<source lang="c">
#if defined MACRO_A
#if defined MACRO_A
Riga 214: Riga 214:
Il linguaggio C definisce anche delle macro:
Il linguaggio C definisce anche delle macro:


==={{IndexItem|__DATE__}}<tt>__DATE__</tt>===
==={{IndexItem|__DATE__}}<code>__DATE__</code>===
La macro <tt>__DATE__</tt> contiene la data della compilazione nel formato mese/giorno/anno.
La macro <code>__DATE__</code> contiene la data della compilazione nel formato mese/giorno/anno.


==={{IndexItem|__FILE__}}<tt>__FILE__</tt>===
==={{IndexItem|__FILE__}}<code>__FILE__</code>===
La macro <tt>__FILE__</tt> contiene il nome del file correntemente in compilazione. Può essere modificata con la direttiva [[##line|#line]].
La macro <code>__FILE__</code> contiene il nome del file correntemente in compilazione. Può essere modificata con la direttiva [[##line|#line]].


==={{IndexItem|__LINE__}}<tt>__LINE__</tt>===
==={{IndexItem|__LINE__}}<code>__LINE__</code>===
La macro <tt>__LINE__</tt> contiene il numero della linea correntemente in compilazione. Può essere modificata con la direttiva [[##line|#line]].
La macro <code>__LINE__</code> contiene il numero della linea correntemente in compilazione. Può essere modificata con la direttiva [[##line|#line]].


==={{IndexItem|__TIME__}}<tt>__TIME__</tt>===
==={{IndexItem|__TIME__}}<code>__TIME__</code>===
La macro <tt>__TIME__</tt> contiene l'ora della compilazione nel formato ore:minuti:secondi.
La macro <code>__TIME__</code> contiene l'ora della compilazione nel formato ore:minuti:secondi.


==={{IndexItem|__STDC__}}<tt>__STDC__</tt>===
==={{IndexItem|__STDC__}}<code>__STDC__</code>===
Il contenuto della macro <tt>__STDC__</tt> varia da compilatore a compilatore. Solitamente, se essa è definita, il compilatore accetterà soltanto codice C standard.
Il contenuto della macro <code>__STDC__</code> varia da compilatore a compilatore. Solitamente, se essa è definita, il compilatore accetterà soltanto codice C standard.





Versione delle 13:02, 28 lug 2018

Indice del libro

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 <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

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

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

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.