Direttive Varie del Preprocessore in Linguaggio C
Con questa lezione concludiamo lo studio del preprocessore del linguaggio C.
Vedremo qui le ultime tre direttive che il precompilatore mette a disposizione: #error
, #line
e #pragma
.
Si tratta di direttive che vengono utilizzate raramente, ma che possono essere molto utili in determinate situazioni.
Direttiva #error
La direttiva di precompilazione #error
ha la seguente sintassi:
#error messaggio
Dove messaggio
è una sequenza di caratteri che rappresenta il messaggio di errore da visualizzare.
Quando il preprocessore incontra la direttiva #error
, interrompe la compilazione e visualizza il messaggio di errore specificato.
Questa direttiva viene adoperata per indicare gravi problemi del programma in fase di compilazione. Infatti, essa viene adoperata sempre in congiunzione con la compilazione condizionale.
Vediamo un esempio. Supponiamo di scrivere un programma che non deve essere compilato per una macchina o sistema che non supporta il tipo floating point. In tal caso, possiamo utilizzare la direttiva #error
per interrompere la compilazione e visualizzare un messaggio di errore.
#if !defined(__STDC_IEC_559__)
#error "Il sistema non supporta il tipo floating point"
#endif
In questo esempio, se il sistema non supporta il tipo floating point, la compilazione verrà interrotta e verrà visualizzato il messaggio "Il sistema non supporta il tipo floating point".
Analogamente, supponiamo che il nostro programma richieda che gli interi int
siano memorizzati usando, almeno, 32 bit o 4 byte. Possiamo scriverere il seguente codice:
#include <limits.h>
#if INT_MAX < 2147483647
#error "Il tipo int è troppo piccolo"
#endif
Nel file limits.h
sono definite le costanti INT_MAX
e INT_MIN
che rappresentano il valore massimo e minimo che un int
può memorizzare. Se un intero int
è rappresentato con 32 bit, allora il massimo che può memorizzare è:
Per cui, se INT_MAX
è minore di 2147483647, allora il tipo int
non utilizza 32 bit e la compilazione verrà interrotta con il messaggio "Il tipo int è troppo piccolo".
Spesso, la direttiva #error
si trova nella clausola #else
di una direttiva #if
o #ifdef
. Ad esempio:
#if defined(__linux__)
/* Codice per Linux */
#else
#error "Questo programma richiede un sistema operativo Linux"
#endif
Direttiva #error
La direttiva di precompilazione #error
interrompe la compilazione e visualizza un messaggio di errore specificato.
La sintassi è:
#error messaggio
Dove messaggio
è il messaggio di errore da visualizzare.
Direttiva #line
La direttiva di precompilazione #line
ha la seguente sintassi:
#line numero "file"
Questa direttiva è raramente utilizzata. Il suo scopo, infatti, è quello di modificare il valore delle macro __LINE__
e __FILE__
. Per cui, ad esempio, se scriviamo:
#line 42 "file.c"
Da questo punto in poi, __FILE__
restituirà "file.c"
e __LINE__
restituirà un valore progressivo a partire da 42.
La seconda conseguenza di questa direttiva, è che qualunque messaggio di errore mostrato dal compilatore indicherà come file file.c
e come numero di riga il numero ottenuto dal numero di righe che seguono la direttiva #line
più 42
.
Perché utilizzare una direttiva di questo tipo? In generale, essa non viene mai utilizzata dagli sviluppatori, ma è utile per i tool di sviluppo e di debug.
Esistono svariati tool che generano codice C. Ad esempio, i parser di linguaggi di programmazione, i compilatori di linguaggi di markup, i tool di generazione di codice, ecc. Questi tool possono utilizzare la direttiva #line
per indicare al compilatore la posizione del codice generato all'interno del file sorgente originale.
Possiamo immaginare, ad esempio, un tool che prende in ingresso un file scritto in un linguaggio chiamato linguaggioX
e genera un file C. Supponiamo che questo tool prenda in ingresso un file con estensione .x
e generi un file con estensione .c
. In tal caso, il tool potrebbe utilizzare la direttiva #line
per indicare al compilatore la posizione del codice generato all'interno del file .x
:
#line 10 "file.x"
In questo modo, se il compilatore trova un errore nel file.c
, il tool può mappare l'errore alla riga corrispondente nel file.x
.
Direttiva #line
La direttiva di precompilazione #line
modifica il valore delle macro __LINE__
e __FILE__
.
La sintassi è:
#line numero "file"
Dove numero
è il numero di riga e file
è il nome del file.
Direttiva #pragma
L'ultima direttiva di precompilazione che vedremo è #pragma
. Questa direttiva è utilizzata per fornire informazioni al compilatore o per controllare il comportamento del compilatore.
La sintassi è:
#pragma comando
Attraverso di essa, possiamo passare comandi specifici al compilatore. Tuttavia, tali comandi non sono standardizzati e possono variare da compilatore a compilatore. Per cui, per conoscere quali sono conviene sempre consultare la documentazione del compilatore che si sta utilizzando.
Lo standard C99 introduce dei comandi standardizzati per la direttiva #pragma
. Li vedremo nel dettaglio in seguito.
Direttiva #pragma
La direttiva di precompilazione #pragma
è utilizzata per inviare comandi specifici al compilatore.
La sintassi è:
#pragma comando
I comandi specifici possono variare da compilatore a compilatore.
In Sintesi
Con questa lezione abbiamo concluso il nostro studio del precompilatore C.
Abbiamo studiato le tre direttive rimanenti: #error
, #line
e #pragma
.
-
La direttiva
#error
interrompe la compilazione e visualizza un messaggio di errore.Essa viene utilizzata per indicare gravi problemi del programma in fase di compilazione e viene sempre usata in congiunzione con la compilazione condizionale.
-
La direttiva
#line
modifica il valore delle macro__LINE__
e__FILE__
. Inoltre, modifica il modo in cui il compilatore conteggia le righe e i file.Essa è utilizzata raramente dagli sviluppatori, ma è utile per i tool di sviluppo e di debug.
-
La direttiva
#pragma
è utilizzata per inviare comandi specifici al compilatore.I comandi specifici possono variare da compilatore a compilatore.