Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

28
Anno accademico 2010-2011 Anno accademico 2010-2011 1 Il preprocessore del Il preprocessore del linguaggio C linguaggio C

Transcript of Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Page 1: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

11

Il preprocessore del linguaggio Il preprocessore del linguaggio CC

Page 2: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

22

SommarioSommario

• Il preprocessoreIl preprocessore La sostituzione di macroLa sostituzione di macro Le compilazioni condizionaliLe compilazioni condizionali L’inclusione di fileL’inclusione di file

Page 3: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

33

• Il preprocessorepreprocessore del linguaggio C è un programma a sé stante, che viene eseguito prima del compilatore, con propri lessico e sintassi, orientati alle linee

• Le principali funzioni offerte dal preprocessore sono: Elaborazione di macroElaborazione di macro Inclusione di file sorgenteInclusione di file sorgente Compilazione condizionaleCompilazione condizionale, che consente di compilare

porzio-ni distinte di codice sorgente in dipendenza del valore di un’espressione aritmetica

• Tutte le direttive per il preprocessore iniziano con il carattere diesisdiesis, (il cancelletto), che deve essere il primo carattere della linea a meno di spazi bianchi

Introduzione Introduzione 1 1

Page 4: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

44

• Le direttive del preprocessore possono apparire ovunque nel codice sorgente (prima, dopo, o inframmezzate a istruzioni C)

• Una definizione di macromacro termina con un newline invece che con un punto e virgola

• Per suddividere una definizione di macro su più linee occorre dunque inserire un backslashbackslash, \\, immediatamente prima del newline

• Esempio: Esempio: define LONG_MACRO “Questa è una macro molto lunga\define LONG_MACRO “Questa è una macro molto lunga\che si estende su due linee” che si estende su due linee”

Introduzione Introduzione 2 2

Page 5: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

55

• Per macromacro si intende un nome a cui è associata una stringa testuale, detta corpo della macrocorpo della macro

• Per convenzione, i nomi di macro dovrebbero essere costituiti da sole lettere maiuscole e dovrebbero essere significativi del contenuto della macro

• Per lo standard ANSI, due nomi di macro sono distinti se differiscono in almeno uno dei primi 31 caratteri

• Quando un nome di macro viene invocato nel codice al di fuori del punto di definizione, viene sostituito dal corpo corpo della macrodella macro: si ha una espansione di macroespansione di macro

• L’utilizzo più comune delle macro consiste nella definizione di costanti numeriche: l’uso diretto di costanti nel codice costituisce una pratica di programmazione scadente, perché il programma diventa difficile da (leggere e) manutenere

La sostituzione di macro La sostituzione di macro 1 1

Page 6: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

66

• Oltre alle macro che definiscono costanti, esiste un’ulteriore forma di macro, simile ad una funzione C, che accetta argomenti che possono essere utilizzati nel corpo della macro

• La sintassi è:

• Esempio:Esempio: define MULT_BY_TWO(a)define MULT_BY_TWO(a) ((a)((a)(a))(a))

)

Argomento di macro define

Corpo di macro

,

(Nome di macro

Sintassi di una macro di tipo Sintassi di una macro di tipo funzionefunzione

La sostituzione di macro La sostituzione di macro 2 2

Page 7: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

77

• MULT_BY_TOMULT_BY_TO può essere utilizzata all’interno del programma, come una funzione: le prestazioni migliorano perché la somma “costa” meno della moltiplicazione

Il parametro attuale 5 viene sostituito al parametro formale aa, in ogni sua occorrenza all’interno del corpo della macro

Le parentesi che delimitano aa ed il corpo della macro sono necessarie per assicurare che il parametro venga istanziato correttamente all’atto dell’espansione della macro

• I parametri di una macro non sono variabili: non è definito il loro tipo, né viene loro assegnata memoria non sono in conflitto con variabili esistenti con lo stesso nome

jj10;10;jjMULT_BY_TWO(5);MULT_BY_TWO(5);

La sostituzione di macro La sostituzione di macro 3 3

Page 8: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

88

• Le macro vengono normalmente eseguite più velocemente delle funzioni, perché non è necessario il salvataggio degli argomenti sullo stack

• Esempio:Esempio: Trasformazione da maiuscole a minuscole, nel caso di codifica ASCII

• La conversione di funzioni in macro comporta effetti significativi sui tempi di esecuzione del programma quando la frequenza di attivazione della funzione è elevata

define TO_LOWER(c) ((c)define TO_LOWER(c) ((c)(‘a’(‘a’‘A’))‘A’))

La sostituzione di macro La sostituzione di macro 4 4

Page 9: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

99

• L’introduzione di un ;; al termine di una definizione di macro è un errore molto diffuso e molto pericoloso

• Esempio:Esempio:

Il punto e virgola diviene parte integrante della stringa da espandere, per cui

L’errore non viene segnalato dal compilatore, che interpreta il secondo punto e virgola come un’istruzione vuota

• Viceversa, produce un errore l’espansione di…

define size 10;define size 10;

x x 10;; 10;;x x size;size;

int array[size];int array[size]; La linea a cui viene fatto riferimento nel messaggio di errore è corretta!

Errori comuni Errori comuni 1 1

Page 10: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

1010

• L’errore più pericoloso si verifica quando, a seguito dell’espansione della macro, l’istruzione risultante è sintatticamente corretta, ma ha una semantica non corrispondente alle attese

• Esempio:Esempio:

Il “;” che segue (var (var 1) 1) viene interpretato come un’istruzione vuota, che costituisce il corpo del ciclo whilewhile la chiamata alla funzione non fa parte del corpo del whilewhile e se varvar coincide con 1 si produce un ciclo infinito

• I compilatori prevedono un’opzione per eseguire solo il preprocessore, così da esaminare il codice risultante dopo l’espansione di tutte le macro

while (var while (var 1); 1); foo(); foo();

define GOOD_CONDITION (var define GOOD_CONDITION (var 1); 1);… … …… … …while GOOD_CONDITIONwhile GOOD_CONDITION foo(); foo();

Errori comuni Errori comuni 2 2

Page 11: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

1111

• Altro errore molto diffuso è l’uso dell’operatore di assegnamento nella definizione di una macro, in analogia all’inizializzazione di variabili

• L’errore può condurre ad anomalie nel codice di difficile individuazione

• Esempio:Esempio:

produrrebbe…

L’assegnamento diviene un’espressione relazionale sintatticamente corretta, che il compilatore non evidenzia errore difficile da rilevare

define MAX define MAX 100100

for(jfor(j100; j>0; j100; j>0; j))for(jfor(jMAX; j>0; jMAX; j>0; j))

Errori comuni Errori comuni 3 3

Page 12: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

1212

• La parentesi sinistra che racchiude il parametro (/i) deve seguire immediatamente il nome della macro, senza la presenza di spazi bianchi: l’errore viene “normalmente” segnalato in compilazione

• Esempio:Esempio:

produrrebbe…

Se invece fosse stato inserito uno spazio bianco, l’espres-sione viene espansa in

perfettamente lecita se aa è un nome di variabile ed ff una funzione

define NEG_A_PLUS_F(a)define NEG_A_PLUS_F(a) (((a)(a)f)f)

j j (x)(x)f;f;j j NEG_A_PLUS_F(x); NEG_A_PLUS_F(x);

j j (a) (a)(a)(a)f(x);f(x);

Errori comuni Errori comuni 4 4

Page 13: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

1313

• Esempio:Esempio:

• Lo standard ANSI stabilisce che, se un nome di macro compare nella propria definizione, allora non viene espanso: si evita il problema delle espansioni infinite

• L’espansione della macro sqrtsqrt produrrebbe…

• Nota:Nota: l’uso di un nome di macro, all’interno della propria definizione, ha senso solo se esiste una funzione con lo stesso nome

define sqrt(x) ((x<0) ? sqrt(define sqrt(x) ((x<0) ? sqrt(x):sqrt(x))x):sqrt(x))

y y ((5<0)((5<0) ?? sqrt(sqrt(5):sqrt(5));5):sqrt(5));

y y sqrt(5);sqrt(5);

L’uso del nome di macro nella L’uso del nome di macro nella definizionedefinizione

Page 14: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

1414

• Dal punto di vista operativo…

…l’utilizzo di una macro o di una funzione non produce un risultato equivalente; infatti: Sul parametro della macro non viene eseguito alcun

controllo di tipo; la funzione (nell’esempio), invece, presuppone un argomento intero e restituisce un valore intero

Se alla funzione viene passata una costante reale, il compilatore può comportarsi diversamente, in dipendenza dell’esistenza del prototipo

MULT_BY_TOMULT_BY_TO può ricevere un parametro aa di tipo qualsiasi

int mult_by_to(a)int mult_by_to(a)int a;int a;{{ return areturn aa;a;}}

define MULT_BY_TWO(a) ((a)define MULT_BY_TWO(a) ((a)(a))(a))

Assenza di controllo per Assenza di controllo per gli argomenti di macro gli argomenti di macro 1 1

Page 15: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

1515

• L’assenza di controlli di tipo sugli argomenti delle macro aggiunge flessibilità alla programmazione

• Esempio:Esempio:•

funziona con aa e bb sia interi che reali• Fra funzioni e macro esiste anche una sostanziale

differenza sul controllo del numero dei parametri, tra definizione e invocazione: Nelle funzioni, il compilatore C effettua il controllo solo se

esiste un prototipo; in caso contrario, la chiamata di funzione viene compilata correttamente, con impredicibilità del comportamento in fase di esecuzione

Per le macro, si ha sempre una segnalazione di errore in fase di compilazione

define MIN(a,b)define MIN(a,b) ((a)<(b)((a)<(b) ?? (a)(a) :: (b))(b))

Assenza di controllo per Assenza di controllo per gli argomenti di macro gli argomenti di macro 2 2

Page 16: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

1616

• Esempio:Esempio:

se bb<cc, bb viene incrementato due volte

• Per non incorrere in comportamenti indesiderati, occorre non utilizzare, nelle chiamate di macro, operatori che implicano effetti collaterali (operatori di incremento, decremento, assegnamento, etc.)

a a ((b ((b)<c)<c ?? (b(b):):(c));(c));

a a MIN(b MIN(b,c);,c);

Gli effetti collaterali Gli effetti collaterali negli argomenti di macro negli argomenti di macro

Page 17: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

1717

• L’uso di espressioni in cui le parentesi non siano utilizzate correttamente, come argomenti di macro, può produrre compor-tamenti indesiderati, a causa della precedenza degli operatori e del bindingbinding

• Esempio:Esempio:

Se si passa alla macro un’espressione aritmetica…

…che assegna il valore 22 a jj, piuttosto che il valore corretto 98

Il corpo e gli argomenti di una macro devono essere sempre racchiusi fra parentesi

define SQUARE(a) adefine SQUARE(a) aaa

j j 2 2 3 3 4 4 3 3 4; 4;j j 22SQUARE(3SQUARE(34);4);

Il binding degli argomentiIl binding degli argomenti

Page 18: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

1818

• La definizione di una macro mantiene la sua validità fino al termine del file sorgente, o fino a quando non viene esplicitamente “cancellata”, per mezzo della direttiva undefundef

• Non è possibile ridefinire una macro senza prima averla cancellata con l’uso della direttiva apposita, a meno che le definizioni coincidano

La cancellazione di una La cancellazione di una definizione definizione di macrodi macro

Page 19: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

1919

• Sia macro che funzioni consentono di rappresentare Sia macro che funzioni consentono di rappresentare con un singolo nome (alias) un insieme di operazioni con un singolo nome (alias) un insieme di operazioni

• VantaggiVantaggi

Le macro sono più veloci, perché non richiedono le operazioni connesse con le chiamate di funzione (salvataggio del contesto)

Il numero degli argomenti delle macro è sempre soggetto a controllo da parte del compilatore

Non è imposto alcun vincolo sul tipo degli argomenti (la stessa macro può essere utilizzata su più tipi di dati)

Macro vs Funzioni Macro vs Funzioni 1 1

Page 20: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

2020

• SvantaggiSvantaggi

Gli argomenti di macro vengono valutati ogni volta che compaiono all’interno del corpo della macro possibili effetti collaterali indesiderati

Il corpo delle funzioni è compilato una sola volta: molteplici chiamate alla stessa funzione usufruiscono dello stesso codice eseguibile; le macro vengono espanse ad ogni occorrenza

Nelle macro non vi è controllo di tipo sugli argomenti; le funzioni definite con prototipi controllano sia il numero che il tipo degli argomenti

La fase di debuggingdebugging per programmi contenenti macro è più complicata: il codice sorgente è sottoposto a due fasi di traduzione il codice oggetto è più “distante” dal sorgente

Macro vs Funzioni Macro vs Funzioni 2 2

Page 21: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

2121

• Il preprocessore consente di selezionare le porzioni di codice che devono essere compilate, attraverso le di-rettive ifif, elseelse, elifelif, endifendif

• Esempio:Esempio:

Codice sorgente C

Espressione condizional

e

endif

if Espressione condizional

e

elif

Codice sorgente C

else

La sintassi delle direttive La sintassi delle direttive di di compilazione compilazione condizionalecondizionale

if x if x 1 1 undef xundef x

define x 0define x 0

elif x elif x 2 2 undef xundef x

define x 3define x 3

elseelse

define y 4define y 4

endifendif

Le compilazioni condizionali Le compilazioni condizionali 1 1

Page 22: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

2222

• L’espressione condizionale contenuta in una direttiva if if o elifelif deve essere una costante, che non deve neces-sariamente essere racchiusa tra parentesi (sono opzionali)

• La direttiva elif elif è equivalente al costrutto else if else if del linguaggio C

• I blocchi di istruzioni dipendenti da una direttiva condizionale di preprocessore non sono racchiusi tra parentesi graffe, ma sono delimitati da un’istruzione elifelif, elseelse, o endif endif

• Ogni blocco if if può contenere un numero qualsiasi di blocchi elifelif, ma un solo blocco elseelse, che deve essere l’ultimo

• Ogni blocco if if deve essere terminato da una direttiva endif endif

Le compilazioni condizionali Le compilazioni condizionali 2 2

Page 23: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

• Inoltre… Le macro che compaiono in un’espressione

condizionale vengono espanse prima della valutazione dell’espressione

Le direttive condizionali di preprocessore possono essere innestate (come gli ifif nel linguaggio C)

Le istruzioni comprese in blocchi condizionali possono essere anche istruzioni del linguaggio C

• Le compilazioni condizionali sono particolarmente utili nella fase di debuggingdebugging, durante lo sviluppo di un programma, per attivare o disattivare porzioni di codice

2323

Le compilazioni condizionali Le compilazioni condizionali 3 3

Page 24: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

• Le direttive Le direttive if if e e endif endif controllano la controllano la compilazione delle istruzioni C racchiuse nel blocco compilazione delle istruzioni C racchiuse nel blocco condizionale, non la loro esecuzione condizionale, non la loro esecuzione

2424

if DEBUGif DEBUG if (exp_debug)if (exp_debug) {{ … … … … … … }}endifendif

Le compilazioni condizionali Le compilazioni condizionali 4 4

Page 25: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

2525

• Le direttive if if e elif elif consentono la compilazione condizionale, in dipendenza del valore di un’espressione aritmetica

• Si può compilare in modo condizionale anche in dipendenza dell’esistenza o meno di una macro, mediante le direttive ifdefifdef, ifndef ifndef e endif endif

Se la macro TESTTEST è definita, viene compilata la prima printf()printf(), altrimenti viene compilata la seconda

ifdef TESTifdef TEST printf(“Questo è un test. \n”);printf(“Questo è un test. \n”);elseelse printf(“Questo non è un test. \n”);printf(“Questo non è un test. \n”);endifendif

Il controllo dell’esistenza Il controllo dell’esistenza di una macro di una macro 1 1

Page 26: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

2626

• Nella maggior parte dei casi è possibile utilizzare if if invece di ifdef ifdef e ifndefifndef, poiché un nome di macro viene espanso a zero se non è definito

• L’eccezione che richiede l’uso di ifdef ifdef e ifndef ifndef è costituita dalle macro definite come zero

• Esempio:Esempio: Si supponga di definire la macro FALSEFALSE come zero…

ifndef FALSEifndef FALSE

define FALSE 0 define FALSE 0

elif FALSEelif FALSE undef FALSEundef FALSE define FALSE 0define FALSE 0

endifendif

FALSEFALSE viene comunque ridefinita se è stata definita come zero, mai altrimenti

if !FALSEif !FALSE

define FALSE 0 define FALSE 0

endifendif

SoluzioneSoluzione

Il controllo dell’esistenza Il controllo dell’esistenza di una macro di una macro 2 2

Page 27: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

2727

• La direttiva include include può presentarsi in uno dei due formati:

…nel primo caso, il preprocessore cerca il file in un insieme di directory dipendenti dal sistema (ad esempio, in UNIX UNIX come in LINUXLINUX, i file standard di include sono contenuti in /usr/include/usr/include)

…nel secondo caso, il preprocessore cerca il file secondo le usuali regole di ricerca per lo specifico sistema operativo (tipicamente la ricerca viene effettuata nella directory corrente); se la ricerca fallisce, si procede come nel primo caso

• Il comando include include consente di includere file di defini-zione comuni, i file headerfile header, che possono essere condivisi da più file sorgente

include “nome_file”include “nome_file”include <nome_file>include <nome_file>

L’inclusione di file L’inclusione di file 1 1

Page 28: Anno accademico 2010-2011 1 Il preprocessore del linguaggio C.

Anno accademico 2010-2011Anno accademico 2010-2011

2828

• I file header sono caratterizzati dall’estensione .h.h e contengono i prototipi di funzione, le definizioni delle strutture dati, delle macro e dei dati globali, necessari alla comunicazione fra moduli

• Scopo dei file header è quello di sintetizzare in un unico file le informazioni comuni, invece di replicarle in ogni file sorgente

si semplifica la programmazione e la manutenzione del codice

• Molti sistemi operativi (UNIXUNIX, LINUXLINUX) forniscono file header contenenti la definizione di strutture interne del SO

• Anche le librerie di runtime prevedono un insieme di file header che occorre includere per poter richiamare le relative funzioni

L’inclusione di file L’inclusione di file 2 2