【问题标题】:Does "&" vs. "&&" actually make a difference for compile-time flags?“&”与“&&”实际上对编译时标志有影响吗?
【发布时间】:2016-09-02 04:51:20
【问题描述】:

我有在编译时标志中使用以下语法的习惯:

#if (defined(A) & defined(B))

通常建议我使用&& 如下:

#if (defined(A) && defined(B))

我知道这两个运算符之间的区别,在普通代码中 && 会短路。但是,以上都由编译器处理。我用什么重要吗?是否因为不评估第二个define() 而对编译时间的影响很小?

【问题讨论】:

  • 当两半为0或1时,没有区别。
  • 不要编写不必要地掩盖其正在做的事情的代码。 C++ 不是 Java。
  • @PeteBecker,我的代码如何掩盖它在做什么?
  • @Catsunami -- 代码使用按位运算符进行逻辑与。
  • @PeteBecker,我不确定这如何使它变得晦涩难懂。它在 boolean 值上使用按位与,这非常清楚。

标签: c++ c compilation


【解决方案1】:

由于defined(SOMETHING) 产生 0 或 1,因此保证两边都是 0 或 1,因此无论您使用 & 还是 &&,这在技术上都没有区别.

主要是关于良好的习惯(使用& 可能会在某些情况下出现错误)以及编写易于通过简单模式匹配掌握的代码。那里的& 会导致毫秒暂停,而人们会考虑它是否可能是位级别的东西。

另一方面,您不能使用关键字and,您可以在普通 C++ 代码中使用它。

注意事项:
¹ 使用 Visual C++,您可以通过强制包含 <iso646.h> 来使用 and

【讨论】:

  • 我可能错误地认为该标准在预处理器条件中不支持and,但它支持任何整数常量表达式(C++11 §16.1 “条件包含”)。通过超频修复。不清楚,因为它说“除了标识符(包括那些在词法上与关键字相同的标识符)被解释如下所述”。
  • 是的,没有说清楚,但and 不是标识符,所以标识符的正常规则不适用。
  • MSVC 已非正式弃用 ISO646 替代令牌。我不太确定为什么,但除非您手动包含标题,否则它们不能用于(任何地方,不仅仅是在预处理器条件中)。或者,您可以抛出 /Ze 开关(禁用 Microsoft 语言扩展,默认情况下使用 /Za 开关启用),然后这些替代标记将随处可用,而无需包含标题。
  • @CodyGray 这听起来像是您和/或 MSVC 将 C 与 C++ 混淆了。 ISO646 替代标记从未在 C 中的任何上下文中可用,除非您包含 <iso646.h>,它将它们全部定义为扩展为传统等价物的宏。相反,在 C++ 中,它们应该可以在任何地方使用,而不包括任何标题。
【解决方案2】:

根据 C99 标准,预处理器中使用的表达式是 C 语言本身定义的常量表达式,并使用相同的引擎进行评估。因此,&& 是一个基于 LHS 短路的逻辑和运算符,& 是一个没有预定义求值顺序的位运算符。

实际上,当与defined() 一起使用时,两者之间没有区别。但是,以下内容会有所不同:

#define A 2
#define B 5
#if (A && B)
printf("A && B\n");
#endif
#if (A & B)
printf("A & B"\n);
#endif

在这种情况下,将输出A && B,但不会输出A & B(因为按位的结果是0

【讨论】:

    【解决方案3】:

    我想在之前的答案中补充一点,在这种情况下它实际上很重要:

    #define A 0
    #define B 21
    #if (A != 0) && (42 / A == B)
    /* ... */
    #endif
    

    这里,如果A == 0,编译器不会崩溃。写(A != 0) & (42 / A == B) 会使编译器抱怨被零除。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-01
      • 2014-03-16
      • 2011-11-11
      • 1970-01-01
      • 1970-01-01
      • 2013-07-04
      • 2018-03-30
      相关资源
      最近更新 更多