2012-05-21 19 views
10

El siguiente código C++ compila y funciona como el programador previsto en GCC (4.0.4)macros del preprocesador como parámetros a otras macros

#define FOO(x,y,z) ((x)*(y)*(z)) 
#define BAR(x) FOO(x,1) 
#define BAZ 3,7 

int main() 
{ 
    return BAR(BAZ); /* interpreted as return ((3)*(7)*(1)); */ 
} 

Sin embargo, las macros provocan un error en Microsoft Visual C++ Express 2010:

main.cpp (7): C4003 advertencia: no suficientes parámetros reales para la macro 'FOO'
main.cpp (7): error C2059: error de sintaxis: ')'

El problema parece ser que el compilador de Microsoft, mientras maneja la macro BAR internamente, no expande la macro BAZ a parámetros que podrían usarse como dos parámetros separados para macro FOO.

De acuerdo con la norma, ¿qué compilador maneja la situación correctamente?

+0

Parece que lo que realmente está buscando es [macros variadas] (http://en.wikipedia.org/wiki/Variadic_macro). – leftaroundabout

+3

@leftaroundabout no parece que él es ... –

+3

@iammilind: ¿Qué falta en el capítulo 16 de la norma? ¿Cómo no es un estándar "real"? –

Respuesta

12

Según 16.3.4 de la norma ISO/IEC 14882: 2003 (C++ Stardard) expansión de macro se realiza como sigue:

  1. invocación Macro se sustituye con la lista de reemplazo de la macro (el cuerpo), donde cada nombre de parámetro (a menos que se vea afectado por # o ##) se sustituye por una macroexpansión completa del argumento correspondiente especificado en macro invocación.
  2. El resultado del paso 1 es vuelto a escanear. Si hay más invocaciones de macros (excepto las que ya se han expandido y se está considerando el texto), se amplían de acuerdo con el mismo procedimiento recursivamente.

La secuencia de pasos para el código que ha especificado es:

  1. BAR(BAZ)
  2. FOO(3,7,1)
  3. ((3)*(7)*(1))

Así GCC es correcto, y VC no lo es. Pero el error del que se queja VC es que FOO tiene 3 argumentos y BAR especifica solo 2 de ellos. Aparentemente, VC intenta detectar errores tan pronto como sea posible y va demasiado lejos en eso.

+1

No entiendo cómo el algoritmo que ha dado corresponde al comportamiento de GCC. Si lo leo correctamente, el algoritmo es el siguiente: 'BAR (BAZ)' es una invocación de 'BAR' con el argumento' BAZ', por lo que se reemplaza con 'FOO (BAZ, 1)'. Esto ahora se vuelve a explorar. La primera macro que encuentra es 'FOO', por lo que ahora intenta expandir' FOO' con los argumentos 'BAZ' y' 1'. Esto no es suficiente argumentos, por lo que el preprocesamiento falla. ¿Por qué volver a escanear 'FOO (BAZ, 1)' expandir el 'BAZ' primero, cuando el escaneo' BAR (BAZ) 'expandió el' BAR' primero? – Mankarse

+0

@Mankarse Gracias, realmente no era lo suficientemente claro. Fijo. –

+0

Gracias por la explicación clara y completa. Aprendí mucho. – Mankarse

Cuestiones relacionadas