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

标签 c++ macros c-preprocessor legacy-code 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)); */
}

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

main.cpp(7): warning C4003: not enough actual parameters for macro 'FOO'
main.cpp(7): error C2059: syntax error : ')'

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

按照标准,哪个编译器能正确处理这种情况?

最佳答案

根据 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 显然试图尽快捕获错误,但做得有点过头了。

关于c++ - 预处理器宏作为其他宏的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10684169/

相关文章:

N 维数组赋值的 C 宏重载

用于创建字符串文字的 C++ 预处理器

c - 通配符风格的 C 预处理器技巧

c++ - 关于 Boost Statechart 中状态变化的通知

c++ - Matlab 与 C++ 之间的 TCP/IP 通信

基于for循环增量的函数指针的C宏扩展

c++ - 将编译错误消息添加到 SFINAE 宏

c++ - Qt LanguageChange 事件 - 找出新的语言

c++ - 如何将空格添加到 concat 预处理器宏?

objective-c - #if 预处理器宏 "running"#ifdef 是 Objective-C 中的后台吗?