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

Wikibooks, manuali e libri di testo liberi.
Contenuto cancellato Contenuto aggiunto
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:
<source lang="c">
<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:
<source lang="c">
<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:
<source lang="c">
<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:
<source lang="c">
<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:


<source lang="c">
<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 è:


<source lang="c">
<syntaxhighlight lang="c">
#line numerolinea "nomefile"
#line numerolinea "nomefile"
</syntaxhighlight>
</source>


Esempio:
Esempio:
<source lang="c">
<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:


<source lang="c">
<syntaxhighlight lang="c">
#undef macro
#undef macro
</syntaxhighlight>
</source>


Esempio:
Esempio:
<source lang="c">
<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:


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


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

Indice del libro

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.