Traccia della lezione Lez19: Lucido 2: Facciamo un esempio: #define AREA(B,H) B * H ... AREA(12,i); Il precompilatore sostituisce AREA con B*H, ma anche B con 12 e H con i: 12 * i; Se c'è uno spazio fra identificatore e parentesi aperta, la macro viene interpretata come macro semplice, cioè come banale sostituzione dell'identificatore con tutto ciò che segue nella riga. Quindi se si scrive "#define INC(x) (x++)" la chiamata "INC(i);" diventa "(i++);", che corrisponde a incrementare i. Al contrario, scrivendo "#define INC (x) ((x)+1)" la chiamata "INC(i);" diventa "(x) ((x)+1)(i);", che non vuol dire nulla. Lucido 4: Le parentesi attorno all'intero corpo della macro e alle singole occorrenze dei parametri sono necessarie per evitare che le regole di precedenza implicite cambino il significato di quanto si scrive. Quindi l'esempio della macro AREA fatto sopra è sbagliato, o quanto meno pericoloso: AREA(12-a,i+2); diventerebbe 12-a * i+2; che non è lo stesso. Si consideri questo ulteriore esempio. Pressione, volume e temperatura di un gas perfetto rispettano la legge: pV/T = kN, dove p è la pressione, V il volume, T la temperatura assoluta, k la costante di Boltzmann e N il numero di molecole considerate. Quindi, si puo' calcolare il volume di un gas come V = kNT/p: #define KELVIN(t) t+273.15 double V = k * N * KELVIN(t)/p; Questa espressione però è sbagliata perché diventa: double V = k * N * t+273.15/p; Il codice MACRO.C consente di gingillarsi con il precompilatore per vedere l'effetto di diverse dichiarazioni di macro con parametri, più o meno attente all'uso delle parentesi. Lucido 5: Che vantaggio c'è ad avere argomenti di tipo indeterminato? Che si può eseguire lo stesso codice su argomenti di tipo qualsiasi, ammesso che la cosa abbia senso. Consideriamo la macro MAX: può capitare di volere conoscere il massimo fra due numeri interi o fra due numeri reali. Se si scrive una funzione per calcolarlo, bisogna specificare se gli argomenti e il risultato devono essere interi o reali. Quindi, o si creano funzioni diverse per i diversi casi (come succede per il calcolo del valore assoluto con le funzioni abs e fabs) oppure si opta per il tipo più esteso (reale, o addirittura double). double max(double a, double b); Ma allora per riportare il risultato nel tipo originario occorre un'istruzione di conversione esplicita, oppure occorre fidarsi delle regole di conversione implicite, con tutti i loro rischi. int a, b, c; c = max(a,b); Una macro, invece, non fa che sostituire testo con testo, e quindi la macro MAX, eseguita su espressioni intere, restituisce un valore intero, eseguita su espressioni reali, valori reali, e così via. int a, b, c; double x, y, z; c = MAX(a,b); diventa c = ((a) > (b) ? (a) : (b)); z = MAX(x,y); diventa z = ((x) > (y) ? (x) : (y));