13

以下 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)); */
}

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

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

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

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

4

1 回答 1

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))

所以 GCC 是对的,而 VC 不是。但是 VC 抱怨的错误是FOO有 3 个参数并且BAR只指定了其中的 2 个。VC 显然试图尽快捕获错误,但做得有点过头了。

于 2012-05-21T11:38:08.193 回答