在下面非常简单的C程序中,预期的编译器错误是什么? gcc给了我1,而MSVC 2013给了我2。
#define foo
#define bar (defined(foo))
#if bar
#error 1
#else
#error 2
#endif
希望我的问题同样简单:
#ifdef foo
#define bar 1
#else
#define bar 2
#endif
答案 0 :(得分:2)
C规范说:
§6.10.1/ 1表达式......可以包含
defined identifier
或defined(identifier)
形式的一元运算符表达式,如果标识符当前被定义为宏,则表达式计算为1
name(即,如果它是预定义的,或者如果它是#define
预处理指令的主题而没有具有相同主题标识符的干预#undef
指令),0
如果不是§6.10.1/ 4将在预处理令牌列表中进行宏调用 控制常量表达式被替换(除了那些修改过的宏名称) 由
defined
一元运算符),就像在普通文本中一样。 如果令牌defined
是 由于此替换过程而生成或使用defined
一元运算符 在宏替换之前与两个指定表单中的一个不匹配,行为是 未定义即可。在由于宏扩展和defined
一元的所有替换之后 运算符已执行,所有剩余的标识符(包括那些词法 用关键字替换为pp-number 0,然后进行每次预处理 令牌被转换为令牌。
(强调我的)
但是,宏替换的方式非常复杂,我认为MSVC将foo
定义为defined(bar)
这是未定义的行为,而GCC正在将foo
定义为1
。由于MSVC当时处于未定义的行为,它会做出奇怪的事情。
正如您所说,最简单的解决方法是
#ifdef foo
#define bar 1
#else
#define bar 2
#endif
答案 1 :(得分:0)
我相信编译器会在名称/宏被定义为名称/宏定义的一部分之后看到所有内容,即作为程序文本,而不是宏文本。
int defined(char s); // prototype of a function named "defined"
#define foo
#define bar defined(foo)
“bar”程序文本中的任何位置现在将被替换为对没有参数的defined()的调用(因为“foo”被定义为空)。