【问题标题】:Idiomatic way to check for non-zero检查非零的惯用方法
【发布时间】:2011-12-15 14:26:11
【问题描述】:

当我想在 C 中检查一个值是否为 0 时,它是如何惯用的?

  • if (!num)
  • if (num == 0)

【问题讨论】:

  • 首选if(0 == num) 如果你必须选择第二而不是第一。不过,第一是最好的选择。
  • @Als if(0 == num),经典的尤达条件
  • @DavidHeffernan:个人选择的 Q 真的。我更喜欢那个。

标签: c if-statement idioms


【解决方案1】:

虽然这是一个品味问题,但我发现这在很大程度上取决于意图。如果该值用作布尔值,! 就可以了。如果值在计算某些东西,则相等更有意义。

if (!isVisible) {...}
if (isVisible == 0) {...} // Intention not as clear as line above.

if (numberOfItems == 0) {...}
if (!numberOfItems) {...} // Intention not as clear as line above.

【讨论】:

    【解决方案2】:

    我总是喜欢第二种方式:

    if (num == 0)
    

    num == 0ptr == NULL 评估为布尔值,即意图。 Java 编译器强制执行这种形式,但 C/C++ 编译器不会。

    最糟糕的例子是:

    if (!strcmp(str, "something"))
    

    这确实将其意图伪装成strcmp 系列函数不返回布尔值,它们返回正数、零或负数(正如@JoachimPileborg 所指出的那样)。

    但是,如果 int 用于表示布尔类型,而 C 没有内置类型,那么这种形式是可以的:

    if (!b)
    

    但这可以通过创建自定义类型来进行自我记录:

    typedef int bool;
    #define true 1
    #define false 0
    
    bool b = true;
    if (!b)
    {
       ... etc
    }
    

    【讨论】:

    • strcmp 就是一个很好的例子。我喜欢在 Objective-C 中,Apple 提供了一个带有 NSOrderedAscendingNSOrderedSameNSOrderedDescending 的枚举,这使得意图比 -1、0 和 1 更清晰。
    • 关于strcmp 的情况,返回值实际上可以是除零之外的任何正值或负值。永远不要与1-1 比较。
    • @JoachimPileborg:同意;你会使用 < 0== 0> 0
    • 哎呀!不! “由于 num == 0 或 ptr == NULL 计算结果为布尔值,这就是意图。Java 编译器强制执行这种形式,但 C/C++ 编译器不会。”这个问题被标记为 C。在 C 中,这些操作不会计算为布尔值。它们评估为 0 或 1,在规范中明确表示为 int 0 或 1。
    • @JamesGreenhalgh:所以你更喜欢这样的东西:char *p = &something; if (p) { ... }?
    【解决方案3】:

    除了例外,其他人告诉你什么!

    不要使用 floatdouble。 IEEE 754 floats/doubles/long doubles(最常用的)通常不包含精确值,因此直接将它们与0比较是愚蠢的(或做if (!floatValue)

    示例:http://ideone.com/PIUflA

    float f = 0.3;
    f -= 0.2;
    f -= 0.1;
    
    if (!f)
    {
        printf("zero\n");
    }
    else
    {
        printf("non zero\n");
    }
    
    if (f == 0)
    {
        printf("zero\n");
    }
    else
    {
        printf("non zero\n");
    }
    

    使用未优化的编译可以返回(在 ideone 上)

    non zero
    non zero
    

    (如果启用优化,编译器可以预先计算一些更高精度的值并将它们四舍五入为0

    【讨论】:

    • 但这不是与0.1 在基数 2 中无法表示有关吗?
    • @Paul 是的(甚至是 0.20.3)。但“为什么”并不真正相关。重要的是"Don't do it with float an double"
    • 给出的原因是错误的。 “通常不包含精确值”是不正确的:浮点类型包含精确值 - 但计算的结果可能不是人们天真的假设。如果将文字“0”分配给浮点数,那么它将始终与“0”进行比较。这对于 -0 也是一样的,因为它比较等于 +0。
    【解决方案4】:

    我认为这取决于上下文。如果变量引用布尔值是更好的首选。否则,第二个更好。

    【讨论】:

    • 我正要写完全一样的东西。
    • 我想我们写的都差不多;)
    【解决方案5】:

    对于编译器,当然没关系。对于人类读者来说确实如此。由于这两种形式都被其他人使用,你应该习惯它们并识别它们。就个人而言,我更喜欢最短的形式,它需要更少的时间(更少的标记,尤其是括号)来阅读和理解。特别是:

    if (!ptr) {}
    if (!strcmp(a,b)) {}
    

    比阅读更容易

    if (ptr != NULL) {}
    if (strcmp(a,b) == 0) {}
    of (0 == strcmp()) {}
    

    最后一种形式让我身体不适。

    【讨论】:

      【解决方案6】:

      就您的风格而言,它已完成,但您希望它完成。我认为这并不重要,只要您始终如一并且清楚您要做什么,或者如果您在英语句子中更好地表达并且可能会强调您在做什么的情况下这样做。

      为了清楚起见,我通常使用if (num == 0),因为当我检查我的代码时,我不需要思考就能理解我在做什么。

      【讨论】:

        【解决方案7】:

        如果您想检查值是否非零,!!value 也可以工作。

        !value 在 value=0 时计算为 1,在 value≠0 时计算为 0。
        第二个! 翻转它,使!!value 在value≠0 时计算为1,在value=0 时计算为0。

        【讨论】:

        【解决方案8】:

        我们可能会争论哪种方式更好,但惯用的,虽然我可以从其他过时的答案中看出,if(!num)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-05-24
          • 2015-05-17
          • 1970-01-01
          • 2021-05-25
          • 1970-01-01
          • 2021-08-06
          • 1970-01-01
          • 2014-12-02
          相关资源
          最近更新 更多