从已设置为defined()结果的宏可以期待什么值?

时间:2014-12-03 18:05:33

标签: c visual-c++ macros visual-c++-2013 msvc12

在下面非常简单的C程序中,预期的编译器错误是什么? gcc给了我1,而MSVC 2013给了我2。

#define foo
#define bar (defined(foo))

#if bar
#error 1
#else
#error 2
#endif

希望我的问题同样简单:

  1. C规范对define()的值有什么看法?我看起来不可能 找到任何谈论将其价值设定为另一个的东西 宏。
  2. 实际的代码不是我可以控制的东西和#34; #if bar"在整个地方使用。更改#define的最简单方法是什么,以便#if bar可以作为"期望"在MSVC?我唯一能想到的就是扩展它:
  3. #ifdef foo
    #define bar 1
    #else
    #define bar 2
    #endif
    

2 个答案:

答案 0 :(得分:2)

C规范说:

  

§6.10.1/ 1表达式......可以包含defined identifierdefined(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”被定义为空)。