【问题标题】:is there a pragmatic reason to use "if (0 == p) " instead of "if (!p)"?使用“if (0 == p)”而不是“if (!p)”是否有实际的理由?
【发布时间】:2011-03-03 22:59:18
【问题描述】:

我倾向于使用逻辑否定运算符来编写 if 语句:

if (!p)
    some_code();

我身边有些人倾向于使用显式比较,所以代码看起来像:

if (FOO == p)
    some_code();

其中 FOO 是 falseFALSE00.0NULL 之一强>等

我更喜欢缩写形式,因为它是:

  • operator!=友好
  • generic programming友好
  • 简洁(甚至更漂亮,至于我)

以其他方式编写(如果有的话)有哪些实用好处?

【问题讨论】:

  • 我不认为你会得到一个不主观的答案。
  • 直接比较真假的人应该被解雇/否则避免,imo。
  • @Heath Hunnicutt:尤其是当他们将 指针truefalse 进行比较时!
  • 奇怪的是没有cmets提到泛型函数,其中!p引入了一种对p类型的要求
  • @Heath -- 我经常想知道为什么与真正相比的人只停留在一个。毕竟,如果if (x == true)if (x) 更好,那if ((x == true) == true) 不是更好吗?

标签: c++ coding-style


【解决方案1】:

为了对比@Erik's answer,我会说使用! 来提高可读性。如果你发现你忽略了它,那就去测试你的眼睛。下一步是什么?避免使用 1,改用 3 - 2?

【讨论】:

  • 哈哈!让我想起了一台机器,我们使用PI/PI 表示“一”以提高存储效率,因为它比数字字符串1 花费的时间少。
  • @Troubadour:我们在这里也有类似的想法——对我来说,规则 readable 包含子规则“不提供我目前不需要的细节”
  • 显然,如果您的读者忽略了!p 中的!,唯一明智的做法就是写!!!p。多个感叹号可以在互联网上使用,它们也可以在代码中使用。
  • 我认为在复合条件下很容易忽略,但这可能是内部解析器缺陷:)
  • @Troubadour:我认为(作为@glowcoder),虽然对于布尔值和指针我可以发现它很自然,但对于整数,它取决于整数可以隐式转换为布尔值的事实,因此我'宁愿在那里看到p != 0
【解决方案2】:

使用(0 == p)(p == 0) 以提高可读性。乍一看,!== 0 更容易被忽视

如果您有忽略编译器警告的习惯,并且想知道何时使用 = 而不是 ==,请使用 (0 == p)

【讨论】:

  • 这里的readability 概念有一个缺陷——读者可能会对p 的类型做出错误的假设,例如读者可能认为它是一个指针,而它是一个整数或双精度,所以这种可读性的下一步将是hungarian notation
  • 你应该使用明确指示类型的常量,我只是没有使用 0.0 或 nullptr 或 NULL 复制粘贴上面的内容
  • 我实际上发现if (p)if (!p)if (p == 0)if (p == 1)if (p != 0) 更具可读性。
  • @Dan 如果 p 是 bool 类型,我只会发现它更具可读性。否则我更喜欢将其转换为布尔值的检查。它几乎和使用 !!p 来测试类对象的真实性的人一样糟糕。
  • @Erik:如果你有无视警告的习惯,请开启-Werror
【解决方案3】:

这取决于p代表什么。

如果 p 表示布尔值/逻辑值,则 (!p) 似乎最合适 - 通常不鼓励与“FALSE”进行比较。我预计这不会引起太多争论。

如果 p 代表一个值,比如一个计数器,那么 (p == 0)(0 == p) 似乎是合适的。 (两者之间通常会有激烈的争论。我发现第一个更具可读性,但第二个避免了一些非常严重的错误。)除了两个选项中哪个更好,我不认为这是一场争论(如,它应该与 0 比较。)

如果 p 代表一个指针,那么你有一些问题。一个称职的 C++ 程序员应该知道(!p) 会告诉你它是否为空。然而,这个可读性的想法是一个灰色地带,我认为这是一场激烈的争论。

【讨论】:

  • 关于严重的错误 --> 严重的编译器警告条件中的意外分配。 +1 用于处理布尔整数和指针不同。对于指针,C++0x 会建议 p != nullptr
【解决方案4】:

有些人声称,实用的好处是,如果您明确地与 NULL、FALSE、0 等进行比较,程序员会发现更容易理解,而逻辑运算符可能会让不了解隐式转换和布尔值在 C/C++ 中工作。

(免责声明:我自己不同意这种观点。if (p) ...if (!p)... 是用 C 和 C++ 表达这一点的惯用方式,而无法理解它们的程序员也没有必要接触 C 或 C++ 代码。 Heath Hunnicutt 的评论已经结束。)

【讨论】:

  • 虽然有很多好的 cmets - 这个答案是关于原始问题的最佳答案。它讲述了“一些程序员”看到的好处,暗示有一大群其他人(包括我)看不到这样的好处
【解决方案5】:

就我个人而言,我有点厌烦从 int 到 boolean 的隐式转换。我认为它不再对 C 语言增加太多。在没有布尔类型的 C89 中,使用整数作为布尔值是完全合理的,在这种情况下,转换会产生好看的代码。我明白为什么它不能被删除,特别是在处理出于兼容性原因不能更改为返回布尔值的库时,现在有一个。但我当然不认为它应该在所有情况下都使用。

有时,整数值 0 表示“没有一个”,但有时它表示“有一个并且为零”。所以我很高兴:

users = get_number_of_users();
if (users) {
    // there are users
    ...
} else {
    // there aren't users
}

我一点也不喜欢:

length = strlen(ptr);
if (length) {
    // there is length? OK, sort of...
} else {
    // there isn't length? No, wait, there *is* a length, that length is 0
}

所以你有实际的理由写if (length == 0)而不是if (!length)。 “如果不是长度”在 英语 中没有意义,因此也不一定是您应该在代码中编写的内容。

诚然,0 被发明为一个特殊的占位符,意思是“没有任何”。但是认识到在许多情况下它可以像其他任何数字一样被视为一个数字,这是数学史上的一个重要突破,我认为我们不应该仅仅因为 C 为我们提供了一种语法来再次对其进行特殊处理而放弃它;-) 如果你想知道一个数是否为 5,你可以将它与 5 进行比较,通常我认为 0 也应该如此。

【讨论】:

  • 惯用的if (!p || !*p) 在英语中也没有意义,但这并不意味着任何人都应该停止使用它。如果程序员想用英语编写代码,他最好使用 pascal 而不是 C/C++。
  • @Andrey:尽管如此,鉴于两个选项之间几乎没有选择,我们必须根据小的原因进行选择。也许你更喜欢if (!length)。我稍微喜欢if (length==0)。我认为我喜欢它的原因是我发现它更直接地表达了意图。另外,我尽量不使用if (!p || !*p)。如果我对空指针和空字符串做同样的事情,那么为什么我的数据方案允许冗余漏掉呢?有时它是不可避免的,有时你可以解决它。
  • 您已将if (length) 考虑在内 - 这种形式已经糟糕了。请注意,最初的问题只涉及惯用的if (!length) 形式,我在所有情况下都非常满意。我更喜欢它而不是模棱两可的0==x / x==0
【解决方案6】:

if (!Foo) 版本的一个尚未提及的好处是它可以与使用 safe bool idiom 的类一起使用。在实现它的类中,类的比较运算符将失败(例如,Foo==0 将未定义)但!Foo 将在 Foo 上调用转换运算符,返回指向成员函数的指针(或空指针,如果 Foo 应该是视为假)。许多 Boost 类,如 shared_ptr,都使用这种技术。

【讨论】:

    【解决方案7】:

    我会在之前和之后放置一个空格!:( ! p) 所以!脱颖而出。但我会将这种用法限制为仅包括指针在内的整数类型。我会将== 用于浮点数,因为它会导致您和其他人停下来思考0.0 == p 是否真的合适而不是指定容差。

    如果p是一个类的实例,( ! p)应该通过定义操作符来使用!避免使用0.0 == p 进行隐式转换。

    【讨论】:

    • 好的,如果您作为原始代码作者知道p 提供operator!= 怎么办?
    【解决方案8】:

    如果语言是 C 并且 p 是指针,那么应该避免使用 if (p) 和 if (!p)。

    C(语言)没有指定空指针为布尔假。 它确实说将 0 强制转换为指针(隐式或显式)将给出空指针。

    因此测试 p 而不是 p == NULL 不一定相同,并且在一些较旧的硬件上它们肯定不一样,因为空指针实际上是指向特定内存页面的指针。

    但是你可以保证 0 和因此 NULL 等于空指针,因为 C 说它们必须是。

    【讨论】:

    • PS:我不知道这如何适用于 C++
    • C99, 6.5.5.3p5 表达式 !E 等价于 (0==E)。 C99, 6.5.9p5 如果一个操作数是指针而另一个是空指针常量,则空指针常量将转换为指针的类型。 C99, 6.3.2.3p3 值为 0 的整数常量表达式,或转换为 void * 类型的此类表达式称为空指针常量。
    【解决方案9】:

    在非常复杂的条件下,使用显式 == 可以帮助使其更具可读性。不幸的是,它也为写 x = 0 而不是 x == 0 打开了大门,但你可以通过写 0 == x 来避免这种情况(这样 0 = x 会抛出错误)。

    这也可能是其他语言的习惯,否则您必须转换为布尔值。

    【讨论】:

    • 有趣的是,显式比较还会带来额外的括号,使复杂条件变得更加复杂
    【解决方案10】:

    我看到的唯一务实的原因是,在第二种情况下,考虑比较的值的类型更明确(例如 foo == null foo 是一个 ponter 类型,!foo 不能说它是否是一个指针, 一个布尔值等)

    【讨论】:

    • 是的,最重要的是你不必关心 p 是什么 :)
    【解决方案11】:

    使用 if (0 == p) 在这种情况下,您可以强制比较进入“如果范围”。我的意思是,如果 p is equals 0 很明显你想这样做。仅使用 (!p) 并不明确您想知道什么。可能是null, false

    【讨论】:

      【解决方案12】:

      if (Foo)if (!Foo) 似乎暗示 Foo 是一个布尔变量,至少对我来说是这样。话虽如此,只要您的标识符具有足够的描述性,它就真的无关紧要了。我会为新代码使用!Foo,但如果有任何约定,请遵循现有约定。一致性胜过一切。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-05-15
        • 2011-12-03
        • 1970-01-01
        • 2010-12-09
        • 1970-01-01
        • 2023-03-19
        • 1970-01-01
        • 2021-10-21
        相关资源
        最近更新 更多