In che modo, esattamente, funziona il trucco a doppia stringa?

Almeno alcuni preprocessori C ti permettono di stringere il valore di una macro, piuttosto che il suo nome, facendolo passare attraverso una macro simile a una funzione ad un’altra che lo stringa:

#define STR1(x) #x #define STR2(x) STR1(x) #define THE_ANSWER 42 #define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */ 

Esempi di utilizzo qui .

Questo funziona, almeno in GCC e Clang (entrambi con -std=c99 ), ma non sono sicuro di come funzioni in termini C-standard.

Questo comportamento è garantito da C99?
Se sì, come lo garantisce C99?
In caso negativo, a che punto il comportamento passa da C definito a GCC?

Sì, è garantito.

Funziona perché gli argomenti delle macro sono a loro volta macro espansi, tranne quando il nome dell’argomento macro viene visualizzato nel corpo della macro con l’identificatore # o il token-paster ##.

6.10.3.1/1:

… Dopo che gli argomenti per l’invocazione di una macro simile a una funzione sono stati identificati, si verifica la sostituzione dell’argomento. Un parametro nell’elenco di sostituzione, a meno che non sia preceduto da un token di preelaborazione # o ## o seguito da un token di preelaborazione ## (vedi sotto), viene sostituito dall’argomento corrispondente dopo che tutte le macro in esso contenute sono state espanse …

Quindi, se fai STR1(THE_ANSWER) , ottieni “THE_ANSWER”, perché l’argomento di STR1 non è espanso in macro. Tuttavia, l’argomento di STR2 viene espanso in macro quando viene sostituito nella definizione di STR2, che pertanto fornisce a STR1 un argomento di 42 , con il risultato di “42”.

Come nota Steve, questo è garantito, ed è stato garantito dallo standard C89 – era lo standard che codificava gli operatori # e ## in macro e mandava ricorsivamente espandendo le macro in args prima di sostituirle nel corpo se e solo se il corpo non applica un # o ## all’argomento. C99 è invariato rispetto a C89 in questo senso.