[C] problemi con #define
Salve a tutti,
ho intrapreso lo studio del libro The C puzzle book e mi sono imbattuto in un problema riguardante il comando al preprocessore #define.
Nel libro c'è il seguente pezzo di codice:
il quale, applicato a questa funzione
dovrebbe scambiare, durante l'esecuzione delle istruzioni del preprocessore, PR(g,a) con printf("a = %g\n", a).
Evidentemente confondo qualcosa, visto che il risultato che mi appare su schermo è
Da quello che posso capire, durante la fase di preprocessore non viene rimpiazzato format con il valore g, il compilatore quindi prende l'istruzione come %f più i caratteri ormat che stampa. Come mai?
ho intrapreso lo studio del libro The C puzzle book e mi sono imbattuto in un problema riguardante il comando al preprocessore #define.
Nel libro c'è il seguente pezzo di codice:
#define PR(format, value) printf("value = %format\n", value)
il quale, applicato a questa funzione
#include <stdio.h> #define PR(format, value) printf("value = %format\n", value) int main() { double a; a = 100 / 3.; PR(g, a); return 0; }
dovrebbe scambiare, durante l'esecuzione delle istruzioni del preprocessore, PR(g,a) con printf("a = %g\n", a).
Evidentemente confondo qualcosa, visto che il risultato che mi appare su schermo è
value = 33.333333ormat
Da quello che posso capire, durante la fase di preprocessore non viene rimpiazzato format con il valore g, il compilatore quindi prende l'istruzione come %f più i caratteri ormat che stampa. Come mai?
Risposte
Dovrei controllare meglio lo standard per verificarlo, ma credo che il problema potrebbe essere la presenza del %. Il preprocessore vede probabilmente la stringa %format e non la riconosce come il suo parametro format. Una possibile soluzione potrebbe essere la seguente:
Stringhe che appaiono una dopo l'altra nel codice vengono automaticamente concatenate. Per cui # format trasforma g in "g" e a questo punto hai le tre stringe "value = %" "g" "\n" che vengono automaticamente concatenate per formare la stringa di formato che ti interessa.
#define PR(format, value) printf("value = %" # format "\n", value)
Stringhe che appaiono una dopo l'altra nel codice vengono automaticamente concatenate. Per cui # format trasforma g in "g" e a questo punto hai le tre stringe "value = %" "g" "\n" che vengono automaticamente concatenate per formare la stringa di formato che ti interessa.
Strano, consultando il libro C: a reference manual di Harbison e Steele leggo che la sintassi del preprocessore è differente dalla sintassi del C; il preprocessore distingue 5 categorie: gli operatori, i separatori, gli identificatori, le parole riservate del linguaggio e le costanti, ma non analizza il testo come fa il compilatore, lo divide in questi tokens e cerca le macro. Non dovrebbe far altro, almeno a quel che ho capito io.
Non capisco cosa trovi di strano. Quella macro non fa altro che usare l'operatore # per convertire quello che viene passato come format in una stringa. Il resto non viene toccato dal preprocessore e viene poi interpretato dal compilatore. È il compilatore C che considera come una singola stringa diverse stringhe scritte una dopo l'altra. Se scrivi insomma "ci" "ao" il compilatore lo interpreterà come "ciao". È utile quando si vuole separare una stringa molto lunga su più righe o quando si vogliono fare cose come questa con il preprocessore.
Non mi riferivo alla tua risposta, che anzi mi è stata di aiuto e per cui ti ringrazio, ma al fatto che il preprocessore non si comporti come mi aspetto di fronte al codice %format, prendendo in considerazione solo %f, ho ricontrollato il manuale sopracitato ma ancora non riesco a trovare una risposta.
Il preprocessore vede quella riga come una lista di token. Se il token è uguale all'argomento questo viene modificato, in caso contrario il token rimane invariato. Il problema della tua riga è che una stringa viene vista come un singolo token, per cui il compilatore non cerca l'argomento al suo interno. Il compilatore (il preprocessore se preferisci) vede insomma "printf(, value)" come i token [ "printf", "(", ""value = %format\n"", ",", "value", ")"] e nessuno di questi verrà sostituito. Spero sia chiaro ora.
Ho capito, grazie.