¿Cuál es la diferencia entre las macros “#define STR (x) #x” y “#define STR (x) VAL (x)” con “#define VAL (x) #x”?

Cuando uso este código:

#include  #define STR(x) #x int main(void) { printf(__FILE__ STR(__LINE__) "hello!\n"); return 0; } 

se imprime

 hello.c__LINE__hello! 

pero cuando uso esto:

 #include  #define STR(x) VAL(x) #define VAL(x) #x int main(void) { printf(__FILE__ STR(__LINE__) "hello!\n"); return 0; } 

se imprime

 hello.c7hello! 

Cuál es la diferencia entre

 #define STR(x) #x 

y

 #define STR(x) VAL(x) #define VAL(x) #x 

Los argumentos a las macros son en sí mismos macro-expandidos, excepto cuando el nombre de los argumentos de macro aparece en el cuerpo de la macro con el modificador # o el token-paster ##.

En el primer caso, el argumento de STR no es macro-expandido, por lo que solo obtiene el nombre de la macro LINE.

En el segundo caso, el argumento de STR se expande en macro cuando se sustituye en la definición de VAL, y por lo tanto funciona: se obtiene el número de línea real porque la macro LINE está expandida.

C99 N1256 borrador preliminar 6.10.3.1/1 “Sustitución de argumentos”:

Después de que se hayan identificado los argumentos para la invocación de una macro similar a una función, tiene lugar la sustitución de argumentos. Un parámetro en la lista de reemplazo, a menos que esté precedido por un token de preproceso # o ## o seguido por un token de preprocesamiento ## (ver más abajo), se reemplaza por el argumento correspondiente después de que todas las macros contenidas en él se hayan expandido. Antes de ser sustituidos, los tokens de preproceso de cada argumento se reemplazan completamente por macro, como si formaran el rest del archivo de preprocesamiento; no hay otras fichas de preprocesamiento disponibles.

Así que # y ## hacen que los argumentos sean tratados de manera diferente.