预处理器宏作为其他宏的参数

ott*_*tto 12 c++ macros legacy-code c-preprocessor visual-studio-macros

下面的C++代码编译并作为GCC上的程序员工作(4.0.4)

#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)); */
}
Run Code Online (Sandbox Code Playgroud)

但是,宏在Microsoft Visual C++ Express 2010上导致错误:

main.cpp(7):警告C4003:宏'
FOO'main.cpp(7)的实际参数不够:错误C2059:语法错误:')'

问题似乎是Microsoft编译器在内部处理BAR宏时,不会将BAZ宏扩展为可用作宏FOO的两个独立参数的参数.

根据标准,哪个编译器正确处理了这种情况?

Ale*_*lin 13

根据ISO/IEC 14882:2003(C++ Stardard)的16.3.4,宏扩展如下进行:

  1. 宏调用将替换为宏的替换列表(正文),其中每个参数名称(除非受#或##影响)将替换为宏调用中指定的相应参数的完整宏扩展.
  2. 重新扫描步骤1的结果.如果其中有更多的宏调用(除了那些已经扩展获得正在考虑的文本的宏调用),它们将根据递归的相同过程进行扩展.

您指定的代码的步骤顺序如下:

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

所以海湾合作委员会是对的,VC不是.但VC抱怨的错误是FOO有3个参数并且BAR只指定其中的2个.VC显然试图尽快发现错误并且有点太过分了.