【问题标题】:Is there a practical reason for "#if defined(X) && (X != 0)"?“#if defined(X) && (X != 0)”有实际原因吗?
【发布时间】:2015-03-04 17:35:12
【问题描述】:

我正在处理一些跨平台的预处理宏。对于微软,我阅读了the following should be used

#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
#   SOME_SETTING_FOR_MY_PROJECT
#endif

以上要点是在使用值之前对WINAPI_FAMILY 进行了显式测试。 (我很确定未定义的宏的计算结果为 0)。

对于 Apple,一些samples on their website use

#if (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
#   SOME_SETTING_FOR_MY_PROJECT
#endif

上面的一点是苹果的样本没有使用#if defined(TARGET_OS_IPHONE) && (TARGET_OS_IPHONE != 0)

一个比另一个更便携吗?

是否有实际理由使用其中一种与另一种?还是风格问题?

注意:我对将 some 定义为 0 而不是让它未定义的风格并不感兴趣。不过,如果它具有实际意义,那么我会对洞察力感兴趣。

【问题讨论】:

    标签: preprocessor c-preprocessor preprocessor-directive


    【解决方案1】:

    尽管未定义的宏确实默认为零(请参阅gcc),但未定义的宏与有意设置为零的宏之间存在差异。

    当然,这对于像 WINAPI_FAMILY 这样的宏没有太大意义,因为它的唯一有效值是 1 和 2。但是某些宏可能在值 0 后面具有合法含义,其含义可能是与未定义的宏不同。

    例如,考虑一个用于记录级别的宏 (LOG_LEVEL),它可以分配给某个级别(LOG_xxx 宏)。如果用户没有定义它,它应该默认为LOG_ERROR(这是2而不是0)。

    #define LOG_NONE     0
    #define LOG_WARNING  1
    #define LOG_ERROR    2
    #define LOG_FATAL    3
    

    现在,如果您只检查 LOG_LEVEL 的值,并且它尚未由用户或编译器定义,它将默认为 LOG_NONE 而不是 LOG_ERROR。因此,在这种情况下,您还需要 defined 检查。

    但除此之外,我认为在大多数情况下它更像是代码风格。我找不到任何不将宏值默认为零的 C 编译器,因此在您的情况下使用 defined 的主要原因是强调这不仅仅是一个值检查,而且还认为宏可能没有设置为全部。

    tldr; 未定义和设置为零不是一回事;但在大多数情况下,defined 的使用是风格或语义强调的问题。

    【讨论】:

      猜你喜欢
      • 2012-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-04
      相关资源
      最近更新 更多