2010-05-01 15 views
74

Al menos algunos C preprocesadores le permiten stringize el valor de una macro, en lugar de su nombre, haciéndolo pasar a través de una macro-función como a otro que stringizes que:¿Cómo funciona exactamente el truco de doble cadena?

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

casos Ejemplo de uso here.

Esto funciona, al menos en GCC y Sonido metálico (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?
En caso negativo, ¿en qué punto el comportamiento pasa de definir C a definir GCC?

+1

Si dices "al menos algo", ¿eso significa que has visto uno donde no funciona? Estoy dispuesto a escribir un informe de error para el proveedor. – Jens

+0

@Jens: No; Yo no. Cada compilador que he usado (a saber, GCC y Clang) implementa este comportamiento. –

Respuesta

69

Sí, está garantizado.

Funciona porque los argumentos para las macros son ellos mismos expandidos macro, excepto donde el nombre del argumento macro aparece en el cuerpo de la macro con el calificador # o el token-paster ##.

6.10.3.1/1:

... Después de los argumentos a favor de la invocación de un argumento de la función como macro han sido identificados, sustitución se lleva a cabo. Un parámetro en la lista de sustitución, a menos que precedido por un # o ## preprocesamiento ficha o seguido de un ## preprocesamiento token (ver más abajo), se reemplazado por el argumento correspondiente después de todas las macros contenida en el mismo haber sido ampliado ...

Así que, si lo hace, entonces obtendrá STR1(THE_ANSWER) "the_answer", porque el argumento de STR1 no es expandidas macro. Sin embargo, el argumento de STR2 es macro expandido 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".

19

Como señala Steve, esto se Guarenteed, y se ha guarenteed ya que la norma C89 - que era el estándar de la codificó el # y ## operadores en las macros y los mandatos de forma recursiva en expansión macros en args antes de la sustitución en el cuerpo si y solo si el cuerpo no aplica un # o ## al argumento. C99 no cambia desde C89 a este respecto.

Cuestiones relacionadas