在C预处理器中,检查宏的定义是否必要?

3

我正在阅读一些C代码,发现像这样的预处理器经常出现:

#if defined(ZERO_MIN_SUPPORT) && (ZERO_MIN_SUPPORT==1)
        minimum = 0x0,
#else
        minimum = 0x1,
#endif

我想知道,与#if ZERO_MIN_SUPPORT相比,它是否有任何优势,还是只是一种编码风格?

在我看来,无论ZERO_MIN_SUPPORT是1、0还是未定义,#if ZERO_MIN_SUPPORT始终等同于#if defined(ZERO_MIN_SUPPORT) && (ZERO_MIN_SUPPORT==1)


1
#if 相当于 #if defined(X) && (x != 0),并不完全等同于 == 1。简而言之,你需要编写 #if X,结果将类似于 #if defined(X) && (x != 0) - i486
4个回答

2
那段特定的代码可以重写成#if ZERO_MIN_SUPPORT==1。不能像你所说的那样重写成#if ZERO_MIN_SUPPORT,因为只要ZERO_MIN_SUPPORT被定义(且不为零),它就会返回1,而不管值是多少。
一般来说,程序员倾向于使用ifdef/#if defined代替#if检查,因为前者在运算符未定义的情况下静默地评估为0。例如:
#if APPLES == ORANGES
  #error Apples are oranges
#endif

如果没有定义任何标识符,这将得出错误的结论。

@nielsen 是的。我已经添加了一条关于这个的注释。 - Lundin

2

在我看来,无论 ZERO_MIN_SUPPORT 的值是1、0还是未定义,#if ZERO_MIN_SUPPORT 总是等价于 #if defined(ZERO_MIN_SUPPORT) && (ZERO_MIN_SUPPORT==1)

所以测试一下吧!

#define ZERO_MIN_SUPPORT 2
#if ZERO_MIN_SUPPORT
#error apparently I am mistaken
#endif

原始版本只有在将ZERO_MIN_SUPPORT定义为1时才匹配。您的版本允许它成为除零以外的任何值。

1
#if ZERO_MIN_SUPPORT==1 是怎么样的情况? - lzhh
ZERO_MIN_SUPPORT定义为2并不是对断言的测试,无论它是1、0还是未定义,#if ZERO_MIN_SUPPORT都等同于#if defined(ZERO_MIN_SUPPORT) && (ZERO_MIN_SUPPORT==1) - Eric Postpischil
没错,但我认为值得指出的是,在面对意外的值时,OP的版本过于脆弱。 - Useless

2
C编程语言标准6.10.3节中可以得知:
预处理指令的形式如下:
#if 常量表达式 换行符 组(可选) #elif 常量表达式 换行符 组(可选)
它们检查控制常量表达式是否求值为非零值
另外,从6.10.4节中可以得知:
在执行完所有宏展开和defined一元运算符的替换后,所有剩余的标识符(包括那些在词法上与关键字相同的标识符)都会被替换为预处理数字0,然后每个预处理记号都会被转换为一个记号。
重点是我加的。
在我看来,无论 ZERO_MIN_SUPPORT 是 1、0 还是未定义,#if ZERO_MIN_SUPPORT 总是等价于 #if defined(ZERO_MIN_SUPPORT) && (ZERO_MIN_SUPPORT==1)
这两者并不等价,因为 #if ZERO_MIN_SUPPORT 测试任何非零值,而 #if defined(ZERO_MIN_SUPPORT) && (ZERO_MIN_SUPPORT==1) 明确测试 1。后者可以缩写为 #if (ZERO_MIN_SUPPORT==1)

2
在我看来,无论ZERO_MIN_SUPPORT是1、0还是未定义,#if ZERO_MIN_SUPPORT始终等同于#if defined(ZERO_MIN_SUPPORT) && (ZERO_MIN_SUPPORT==1)
这是一个事实,而不仅仅是一种观点,我们可以通过评估所有可能性来证明: | ZERO_MIN_SUPPORT | #if ZERO_MIN_SUPPORT | #if defined(ZERO_MIN_SUPPORT) && (ZERO_MIN_SUPPORT==1) | |---|---|---| | 1 | true | true | | 0 | false | false | | undefined | false | false |
然而,在你列出的选项之外,它们是有区别的: | ZERO_MIN_SUPPORT | #if ZERO_MIN_SUPPORT | #if defined(ZERO_MIN_SUPPORT) && (ZERO_MIN_SUPPORT==1) | |---|---|---| | 2 | true | false |
我想知道,与#if ZERO_MIN_SUPPORT相比,它是否有任何优势,或者只是一种编码风格?
在没有对人类使用其中一种方法犯错的频率进行任何研究的情况下,一个是否比另一个具有优势很大程度上是一种观点和推测问题。通常,如果代码不必要地晦涩难懂,较短或更简单的代码更受青睐。除非有某些理由将除了未定义、0和1以外的定义视为false,否则前者执行所需的功能并且更简单更短。
如果有某些理由将其他定义视为false,则#if ZERO_MIN_SUPPORT == 1执行该操作,并且比原始代码更简单更短。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接