¿Por qué estos bloques de código producen resultados diferentes?Intentando comprender el preprocesador C
Algunos código común:
#define PART1PART2 works
#define STRINGAFY0(s) #s
#define STRINGAFY1(s) STRINGAFY0(s)
caso 1:
#define GLUE(a,b,c) a##b##c
STRINGAFY1(GLUE(PART1,PART2,*))
//yields
"PART1PART2*"
caso 2:
#define GLUE(a,b) a##b##*
STRINGAFY1(GLUE(PART1,PART2))
//yields
"works*"
caso 3:
#define GLUE(a,b) a##b
STRINGAFY1(GLUE(PART1,PART2*))
//yields
"PART1PART2*"
estoy usando MSVC++ 2005 SP1 de VS.net
Editar: es actualmente mi creencia de que el preprocesador funciona así: cuando la expansión de macros Paso 1: - tome el cuerpo - eliminar cualquier espacio en blanco alrededor de ## operadores - analizar la cadena, en el caso de que se encuentre un identificador que coincida con el nombre de un parámetro: -si está al lado de un operador ##, reemplace el identificador con el valor literal del parámetro (es decir, la cadena pasó) -si NO está al lado de un operador ##, primero ejecute todo este proceso de explicación sobre el valor del parámetro, luego reemplace el identificador con ese resultado. (ignorando el single '#' atm caso stringafy) -remove todos los ## operadores
Paso 2: - tomar esa cadena resultante y analizarlo para cualquier macro
ahora, desde que yo creo que todos 3 casos deben producir exactamente la misma cadena resultante:
PART1PART2 *
y por lo tanto después de la etapa 2, debe resultar en
obras *
pero al menos debería dar como resultado lo mismo.
no debería 1 y caso 2 resultan en lo mismo, ¿entonces? – matt
¿qué es un "token de preprocesador válido"? tal vez un identificador? en ese caso, no veo cómo funcionaría ninguno de ellos. Supongo que el caso 2 - el único que funciona - es el único que pasa identificadores legales a todos los parámetros ... – matt
@matt, ningún caso 1 simplemente no está definido, por lo que no puede saber qué es lo que el compilador elige para resolver ese problema . –