Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro...

27
damenti di Informatica I damenti di Informatica I a.a. 2008-09 a.a. 2008-09 1 Il linguaggio C Il linguaggio C Il preprocessore Il preprocessore La sostituzione di macro La sostituzione di macro Le compilazioni condizionali Le compilazioni condizionali L’inclusione di file L’inclusione di file C C Language Language

Transcript of Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro...

Page 1: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 1

Il linguaggio CIl linguaggio C

Il preprocessoreIl preprocessoreLa sostituzione di macroLa sostituzione di macroLe compilazioni condizionaliLe compilazioni condizionaliL’inclusione di fileL’inclusione di file

C Language

C Language

Page 2: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 2

Il preprocessoreIl preprocessore

Page 3: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 3

Introduzione Introduzione 1 1

Il preprocessorepreprocessore del linguaggio C è un programma a sé stante, che viene eseguito prima del compilatore, con propria sintassi e grammatica, orientate 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 porzioni 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

Page 4: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 4

Introduzione Introduzione 2 2

Le direttive del preprocessore possono apparire ovunque nel codice sorgente (prima, dopo, o inframezzate a istruzioni C)Una definizione di macromacro termina con un newlinenewline invece che con un punto e virgolaPer suddividere una definizione di macro su più linee occorre dunque inserire un backslashbackslash, \\, immediatamente prima del newline

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

Page 5: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 5

La sostituzione di macro La sostituzione di macro 1 1

Per macro macro 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’uso 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

Page 6: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 6

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 macroLa sintassi è:

EsempioEsempio:

La sostituzione di macro La sostituzione di macro 2 2

define MULT_BY_TWO(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

Page 7: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 7

La sostituzione di macro La sostituzione di macro 3 3

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 macroLe parentesi che delimitano aa ed il corpo della macro sono necessarie per assicurare la corretta istanziazione del parametro quando la macro viene espansa

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

j 10;

j MULT_BY_TWO(5);

Page 8: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 8

La sostituzione di macro La sostituzione di macro 4 4

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

EsempioEsempio: 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) (‘a’ ‘A’))

Page 9: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 9

Errori comuni Errori comuni 1 1

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

EsempioEsempio:

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 vuotaViceversa, produce un errore l’espansione di…

define size 10;

x 10;;x size;

int array[size];

La linea a cui viene fatto riferimento nel messaggio di errore è corretta!

Page 10: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 10

Errori comuni Errori comuni 2 2

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

EsempioEsempio:

Il “;” che segue (var 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 infinitoI compilatori prevedono un’opzione per eseguire solo il preprocessore, così da esaminare il codice risultante dopo l’espansione di tutte le macro

while (var 1); foo();

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

Page 11: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 11

Errori comuni Errori comuni 3 3

Altro errore molto diffuso è l’uso dell’operatore di assegnamento nella definizione di una macro, in analogia all’inizializzazione di variabiliL’errore può condurre ad anomalie nel codice di difficile individuazioneEsempioEsempio:

produrrebbe…

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

define MAX 100

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

Page 12: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 12

Errori comuni Errori comuni 4 4

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

EsempioEsempio:

produrrebbe…

Se invece fosse stato inserito uno spazio bianco, l’espressione viene espansa in

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

define NEG_A_PLUS_F(a) ((a) f)

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

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

Page 13: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 13

L’uso del nome di macro L’uso del nome di macro nella definizionenella definizione

EsempioEsempio:

Lo standard ANSI stabilisce che, se un nome di macro compare nella propria definizione, allora non viene espanso: si evita il problema delle espansioni infiniteL’espansione della macro sqrtsqrt produrrebbe…

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

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

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

y sqrt(5);

Page 14: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 14

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

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 interoSe alla funzione viene passata una costante reale, il compilatore può comportarsi diversamente, in dipendenza dell’esistenza del prototipo (in assenza di prototipo il risultato è imprevedibile)

MULT_BY_TOMULT_BY_TO può ricevere un parametro aa di tipo qualsiasi

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

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

Page 15: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 15

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

L’assenza di controlli di tipo sugli argomenti delle macro aggiunge flessibilità alla programmazioneEsempioEsempio:

funziona con aa e bb sia interi che realiFra 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 funzione viene compilata correttamente, con impredicibilità del comportamento in fase di esecuzionePer le macro, si ha una segnalazione di errore in fase di compilazione

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

Page 16: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 16

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

EsempioEsempio:

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 ((b)<c ? (b) : (c));

a MIN(b, c);

Page 17: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 17

Il binding degli argomentiIl binding degli argomenti

L’uso di espressioni in cui le parentesi non siano utilizzate correttamente, come argomenti di macro, può produrre comportamenti indesiderati, a causa della precedenza degli operatori e del bindingbindingEsempioEsempio:

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

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

Page 18: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 18

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

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

Page 19: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 19

Macro vs Funzioni Macro vs Funzioni 1 1

Sia macro che funzioni consentono di rappresentare con un singolo nome un insieme di operazioni

VantaggiVantaggiLe 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 compilatoreNon è imposto alcun vincolo sul tipo degli argomenti (la stessa macro può essere utilizzata su più tipi di dati)

Page 20: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 20

Macro vs Funzioni Macro vs Funzioni 2 2

SvantaggiSvantaggiGli argomenti di macro vengono valutati ogni volta che compaiono all’interno del corpo della macro possibili effetti collaterali indesideratiIl corpo delle funzioni è compilato una sola volta: molteplici chiamate alla stessa funzione usufruiscono dello stesso codice eseguibile; le macro vengono espanse ad ogni occorrenzaNelle macro non vi è controllo di tipo sugli argomenti; le funzioni definite con prototipi controllano sia il numero che il tipo degli argomentiLa 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

Page 21: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 21

Le compilazioni condizionali Le compilazioni condizionali 1 1

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

EsempioEsempio:

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 1 undef x define x 0elif x 2 undef x define x 3else define y 4endif

Page 22: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 22

Le compilazioni condizionali Le compilazioni condizionali 2 2

L’espressione condizionale contenuta in una direttiva ifif o elifelif deve essere una costante, che non deve necessariamente essere racchiusa tra parentesi (sono opzionali)

La direttiva elifelif è equivalente al costrutto else ifelse 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 endifendif

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

Ogni blocco ifif deve essere terminato da una direttiva endifendif

Page 23: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09

Inoltre…Le macro che compaiono in un’espressione condizionale vengono espanse prima della valutazione dell’espressioneLe 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 codiceLe direttive Le direttive if e if e endif controllano la compilazione delle endif controllano la compilazione delle istruzioni C racchiuse nel blocco condizionale, non la loro istruzioni C racchiuse nel blocco condizionale, non la loro esecuzioneesecuzione

23

Le compilazioni condizionali Le compilazioni condizionali 3 3

if DEBUG if (exp_debug) { … … … }endif

Page 24: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 24

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

Le direttive ifif e elif elif consentono la compilazione condizionale, in dipendenza del valore di un’espressione aritmeticaSi può compilare in modo condizionale anche in dipendenza dell’esistenza o meno di una macro, mediante le direttive ifdefifdef, ifndefifndef e endifendif

Se la macro TESTTEST è definita, viene compilata la prima

printf()printf(), altrimenti viene compilata la seconda

ifdef TEST

printf(“Questo è un test. \n”);

else

printf(“Questo non è un test. \n”);

endif

Page 25: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 25

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

Nella maggior parte dei casi è possibile utilizzare ifif invece di ifdefifdef e ifndefifndef, poiché un nome di macro viene espanso a zero se non è definitoL’eccezione che richiede l’uso di ifdefifdef e ifndef ifndef è costituita dalle macro definite come zero

EsempioEsempio: Si supponga di definire la macro FALSEFALSE come zero…

ifndef FALSE

define FALSE 0

elif FALSE undef FALSE define FALSE 0

endif

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

if !FALSE

define FALSE 0

endif

SoluzioneSoluzione

Page 26: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 26

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

La direttiva includeinclude 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 UNIXUNIX 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 includeinclude consente di creare file di definizione comuni, i file headerfile header, che possono essere condivisi da più file sorgente

include “nome_file”

include <nome_file>

Page 27: Fondamenti di Informatica I a.a. 2008-09 1 Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.

Fondamenti di Informatica I Fondamenti di Informatica I a.a. 2008-09 a.a. 2008-09 27

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

I file header sono caratterizzati dall’estensione .h.h e contengono 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