¿Cómo funciona exactamente el truco de doble cadena?

Al menos algunos preprocesadores C le permiten escribir en cadena el valor de una macro, en lugar de su nombre, pasándola a través de una macro de función a otra que la engarza:

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

Ejemplo de casos de uso aquí .

Esto funciona, al menos en GCC y Clang (ambos con -std=c99 ), pero no estoy seguro de cómo funciona en términos C-estándar.

¿Este comportamiento está garantizado por C99?
Si es así, ¿cómo lo garantiza C99?
De lo contrario, ¿en qué punto el comportamiento pasa de definir C a definir GCC?

Sí, está garantizado

Funciona porque los argumentos a las macros son macro expandidos, excepto cuando el nombre del macro argumento aparece en el cuerpo de la macro con el stringifier # o token-pasteter ##.

6.10.3.1/1:

… Después de que se hayan identificado los argumentos para la invocación de una macro de función, se produce la sustitución de los argumentos. Un parámetro en la lista de reemplazo, a menos que sea precedido por un token de preprocesamiento # o ## o seguido por un token de preprocesamiento ## (ver a continuación), se reemplaza por el argumento correspondiente después de que se hayan expandido todas las macros contenidas en él …

Entonces, si haces STR1(THE_ANSWER) entonces obtienes “THE_ANSWER”, porque el argumento de STR1 no se expande macro. Sin embargo, el argumento de STR2 se expande macro cuando se lo sustituye en la definición de STR2, lo que le da a STR1 un argumento de 42 , con el resultado de “42”.

Como señala Steve, esto está garantizado, y se ha garantizado desde el estándar C89: ese fue el estándar codificado los operadores # y ## en macros y obliga a expandir recursivamente las macros en args antes de sustituirlas en el cuerpo si y solo si el cuerpo no aplica un # o ## al argumento. C99 no cambia desde C89 a este respecto.