预处理器宏作为其他宏的参数 < >下面的C++代码编译和工作在GCC(4.0.4)上的程序员 但是,宏在微软Visual C++快速表2010:上会引起错误。
main.cpp(7):警告C4003:宏“FOO”的实际参数不足预处理器宏作为其他宏的参数 < >下面的C++代码编译和工作在GCC(4.0.4)上的程序员 但是,宏在微软Visual C++快速表2010:上会引起错误。,c++,macros,c-preprocessor,legacy-code,visual-studio-macros,C++,Macros,C Preprocessor,Legacy Code,Visual Studio Macros,main.cpp(7):警告C4003:宏“FOO”的实际参数不足 main.cpp(7):错误C2059:语法错误:')' 问题似乎在于,Microsoft编译器在内部处理BAR宏时,没有将BAZ宏扩展到可以用作宏FOO的两个单独参数的参数 根据标准,哪个编译器正确处理这种情况?根据ISO/IEC 14882:2003(C++标准)的16.3.4,宏扩展执行如下: 宏调用被替换为宏的替换列表(主体),其中每个参数名(除非受#或###影响)被替换为宏调用中指定的相应参数的完整宏展开 重新扫描步骤
main.cpp(7):错误C2059:语法错误:')' 问题似乎在于,Microsoft编译器在内部处理BAR宏时,没有将BAZ宏扩展到可以用作宏FOO的两个单独参数的参数
根据标准,哪个编译器正确处理这种情况?根据ISO/IEC 14882:2003(C++标准)的16.3.4,宏扩展执行如下:
BAR(BAZ)
FOO(3,7,1)
((3)*(7)*(1))
所以GCC是对的,VC不是。但是VC抱怨的错误是,
FOO
有3个参数,BAR
只指定了其中的2个。VC显然试图尽快发现错误,但做得有点过火。似乎你真正想要的是。@leftaroundabout似乎不是…@iammilind:标准第16章缺少什么?这怎么不是一个“真正的”标准呢?@iammilind当然是这样。它的设计允许在实现中有一定的回旋余地,某些涉及标记粘贴的操作会导致未定义的行为,但这里的情况并非如此。(通常,在存在未定义行为的情况下,g++会发出错误信号,大多数其他编译器都会接受它。)@CharlesBaily,你是对的。删除评论(登录到PC后)。我不明白您给出的算法如何对应GCC行为。如果我读对了,算法如下:BAR(BAZ)
是对BAR
的调用,带有参数BAZ
,因此被替换为FOO(BAZ,1)
。现在将对其进行重新扫描。它找到的第一个宏是FOO
,因此现在它尝试用参数BAZ
和1
展开FOO
。这是不够的参数,因此预处理失败。当扫描BAR(BAZ)
时,为什么重新扫描FOO(BAZ,1)
首先展开BAZ
,首先展开BAR
?感谢您的清晰完整的解释。我学到了很多。
#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)); */
}