【问题标题】:What happens when I define macros with the same name当我定义具有相同名称的宏时会发生什么
【发布时间】:2018-03-23 10:14:41
【问题描述】:

当我在一个源文件中有多个同名#defines 时会发生什么:

例如:

#define Dummy 1
#define Dummy 2

我不打算使用它,但在生产代码中看到了类似的东西。标准是否涵盖了这一点?

【问题讨论】:

  • 请注意,您可以试试这个。
  • @Jean-FrançoisFabre 这将为我提供我使用的特定(预)编译器的答案,但如果我使用另一个编译器可能会改变。这就是我问的原因。
  • @Lundin 如果行为是实现定义的还是未定义的,不同的编译器会做不同的事情。如果这是其中之一,那么经验测试将毫无价值。
  • @Lundin:任何 C 实现,无论它多么严格地符合标准,都只是所有可能符合 C 实现的集合中的一个元素,既不能传达关于集合的全部信息,也不能具有权威性.
  • @Lundin:事实上,您必须知道 C 标准首先说明了什么,这意味着您之前的“然后使用标准 C 编译器”的声明没有用。使用标准 C 编译器并不能回答 C 标准所说的问题。

标签: c c-preprocessor language-lawyer


【解决方案1】:

这是违反约束的,因此需要符合标准的编译器来发出诊断。

C11, 6.10.3 Macro replacement 状态:

当前定义为类对象宏的标识符不应由另一个#define 预处理指令重新定义,除非第二个定义是类对象宏定义并且两个替换列表相同。 [..]

如前所述,如果替换相同,则不违反约束。所以

#define X 1
#define X 2

需要诊断;而

#define X 1
#define X 1

没问题。类似的约束适用于类似函数的宏 (C11, 6.10.3, 2)。

【讨论】:

  • 所以说最后一个是活跃的并不安全。它或多或少是未定义的?
  • 违反约束会导致未定义的行为吗? C标准没有明确说明。但是在没有 defined 行为的情况下,断定它是未定义的可能是合乎逻辑的。
  • @KamiKaze 是的,假设这样是不安全的。违反约束与未定义的行为相同。
  • @P.P.违反约束反而会导致“违反 C 语言”,因此情况更糟。我知道有一些文字说,如果违反了“应”/“不应”外部约束,那么就有 UB。这意味着如果违反了约束,我们会遇到比 UB 更糟糕的情况。除了“必须发出诊断消息”之外,我认为该标准没有其他术语。
  • it's not a constraint violation if the replacement is identical
【解决方案2】:

这个:

#define Dummy 1
#define Dummy 2

等同于:

#define Dummy 2

但是您可能会收到(我不确定标准是怎么说的)警告,例如 'Dummy': macro redefinition 第二个 #define

换句话说:最后一个#define获胜。

如果你想把事情做好,你应该使用#undef

#define Dummy 1
#undef Dummy
#define Dummy 2    // no warning this time

顺便说一句:在某些情况下,更改宏的定义是完全可以的。

【讨论】:

  • 如果#define 的值相同,您不会收到警告
  • 重新定义没有undefine的宏在技术上是无效的。
  • 如果它违反了 C 标准,那么推理将会发生什么是没有意义的。违反约束与未定义的行为相同。因此,您在这个问题中描述的“最后定义获胜”的行为绝不是给定的,也不应该被依赖。
  • @Lundin:在同一个问答中,你们都告诉我们使用符合标准的 C 编译器来识别问题中询问的行为,并且用于告知此答案的编译器行为并不表示标准。
  • @MichaelWalz:我们都缺乏 C-norm-fu :) 这似乎是实现定义的。 gcc 用户(不知道 clang)对您的回答没有意见。也许不是 Turbo-C 的 :)
【解决方案3】:

来自 C 标准#6.10.3.5p8 的示例

示例 6 为演示重定义规则,以下序列有效

      #define      OBJ_LIKE      (1-1)
      #define      OBJ_LIKE      /* white space */ (1-1) /* other */
      #define      FUNC_LIKE(a)   ( a )
      #define      FUNC_LIKE( a )( /* note the white space */ \
                                   a /* other stuff on this line
                                       */ ) 

但以下重新定义无效

      #define      OBJ_LIKE    (0)     // different token sequence
      #define      OBJ_LIKE    (1 - 1) // different white space
      #define      FUNC_LIKE(b) ( a ) // different parameter usage
      #define      FUNC_LIKE(b) ( b ) // different parameter spelling

[强调我的]

因此,这个

#define Dummy 1
#define Dummy 2

无效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-04
    • 1970-01-01
    • 2021-04-28
    • 1970-01-01
    相关资源
    最近更新 更多