【问题标题】:What is the value of an undefined constant used in #if?#if 中使用的未定义常量的值是多少?
【发布时间】:2011-07-02 09:45:07
【问题描述】:

为了评估 #if 条件,我的预处理器似乎假定未定义的常量为 0。

这可以依赖,还是未定义的常量会给出未定义的行为?

【问题讨论】:

    标签: c++ c-preprocessor


    【解决方案1】:

    OP 专门询问了 C 预处理器,第一个答案是正确地引用了 C 预处理器规范。但是其他一些 cmets 似乎模糊了 C 预处理器和 C 编译器之间的区别。需要明确的是,这是两个不同的东西,有不同的规则,它们在两个不同的通道中应用。

    #if 0 == NAME_UNDEFINED
    int foo = NAME_UNDEFINED;
    #endif
    

    此示例将成功输出 foo 定义,因为 C 预处理器将 NAME_UNDEFINED 作为条件表达式的一部分计算为 0,但生成编译器错误,因为初始化器未作为条件表达式计算,然后 C 编译器将其计算为一个未定义的符号。

    【讨论】:

      【解决方案2】:

      是的,可以信赖。 C99 标准在 §6.10.1 ¶3 中指定:

      由于宏扩展和定义的一元的所有替换 运算符已执行,所有剩余的标识符都替换为 pp 号 0

      编辑

      对不起,我以为是 C 题;不过,没什么大不了的,C++ 标准(§16.1 ¶4)中的等效部分指出:

      由于宏扩展和定义的一元运算符的所有替换 已执行,所有剩余的标识符和关键字,除了truefalse,都替换为pp 编号0

      唯一的区别是truefalse的处理方式不同,在C中不需要特殊处理,而在C++中即使在预处理阶段它们也有特殊含义。

      【讨论】:

      • 只是好奇:编译器为什么这样做?当表达式未定义并且编译器无论如何都知道这一点时,为什么编译器不能抛出错误消息?这不会导致软件中出现不必要的错误。我真的很困惑为什么新的编译器不处理这个问题。仅仅是因为必须保持向后兼容性还是什么?
      • 这就是规范所说的,它可能形式化了现有行为(C 预处理器可以追溯到 70 年代);如果想要正确实现 C 语言,即使是现代编译器也无法决定采取不同的做法,而现在更改规范可能会破坏大量代码。
      【解决方案3】:

      未定义为宏的标识符在计算表达式之前转换为0

      例外是标识符true,它被转换为1。这是特定于 C++ 预处理器的;在 C 中,这不会发生,您需要包含 <stdbool.h> 才能以这种方式使用 true,在这种情况下,它将被定义为宏并且不需要特殊处理。

      【讨论】:

      • 在 C++ 中,true 是关键字而不是宏——它的解释与预处理器无关,因此也不例外。
      • @Clifford,如果您在诸如#if whatever == true 之类的预处理器指令中使用true,则whatevertrue 都是普通标识符。预处理器有自己的语言,所以需要特殊的大小写。
      猜你喜欢
      • 2013-03-14
      • 1970-01-01
      • 2012-08-27
      • 2011-05-20
      • 1970-01-01
      • 2014-08-27
      • 2018-12-28
      • 2016-08-19
      相关资源
      最近更新 更多