【问题标题】:Why 2 NULL pointers do not evaluate to false?为什么 2 个 NULL 指针不会评估为假?
【发布时间】:2012-04-22 21:46:10
【问题描述】:

我有一个相对简单的算法,它遍历 std::vector 寻找两个相邻的元组。一旦找到 X 值的左右元组,我就可以在它们之间进行插值。不知何故,这是可行的:

  std::vector<LutTuple*>::iterator tuple_it;
  LutTuple* left = NULL;
  LutTuple* right = NULL;
  bool found = 0;

  // Only iterate as long as the points are not found
  for(tuple_it = lut.begin(); (tuple_it != lut.end() && !found); tuple_it++) {
    // If the tuple is less than r2 we found the first element
    if((*tuple_it)->r < r) {
        left = *tuple_it;
    }
    if ((*tuple_it)->r > r) {
        right = *tuple_it;
    }
    if(left && right) {
        found = 1;
    }
  }

此时:

  std::vector<LutTuple*>::iterator tuple_it;
  LutTuple* left = NULL;
  LutTuple* right = NULL;

  // Only iterate as long as the points are not found
  for(tuple_it = lut.begin(); tuple_it != lut.end() && !left && !right; tuple_it++) {
    // If the tuple is less than r2 we found the first element
    if((*tuple_it)->r < r) {
        left = *tuple_it;
    }
    if ((*tuple_it)->r > r) {
        right = *tuple_it;
    }
  }

没有。这是为什么?我希望像这样的两个 NULL ptr 在被否定时一起评估为真。

【问题讨论】:

标签: c++ pointers null boolean


【解决方案1】:

一旦找到任何一个,第二个循环就会终止。将条件更改为:

tuple_it != lut.end() && !(left && right)

tuple_it != lut.end() && (!left || !right)

继续直到找到两者。

【讨论】:

    【解决方案2】:

    我希望像这样的两个 NULL ptr 在以下情况下一起评估为真 否定。

    这没有意义。不要“否定”指针并期望它们在强制进入布尔表达式时会评估什么。相反,我建议明确地将它们与 NULL 进行比较。

    另外,将用于继续循环的复杂布尔表达式移到单独的行中,否则很难在逻辑上遵循代码。

    【讨论】:

    • 从指针到布尔值的标准转换是明确定义的。选择是使用该比较还是明确比较纯粹是为了审美。
    • @Mike,我的答案涉及可读性,而不是正确性。我确信代码在编写时表现“正确” - 只是它没有按照作者的预期行事,所以问题主要在于使其更具可读性和不易出错。
    • 人们可以很容易地争辩说标准转换更具可读性且不易出错;选择纯粹是审美,你的个人喜好与这个问题无关。
    • 我通常同意“null 为 false”有点蹩脚。但这是惯例,尤其是对于共享指针,运算符重载使代码保持简洁:hostilefork.com/2009/10/26/treating-non-booleans-as-logic
    • @MikeSeymour 这不是纯粹的审美。这种转换让很多人感到困惑。包括我自己,但从我看到的关于使用 stdchr 的返回值之类的错误数量来看,显然我并不孤单。
    【解决方案3】:

    有一个逻辑问题。

    在第一个 sn-p 中,您(基本上)拥有!(left &amp;&amp; right)

    在第二个 sn-p 中你有:!left &amp;&amp; !right

    它们不等价。

    如果你建立真值表,你会发现!(left &amp;&amp; right)等价于(!left || !right)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-11
      • 2019-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多