【问题标题】:Issues with commutative property of && operator&& 运算符的交换属性问题
【发布时间】:2019-02-21 09:19:07
【问题描述】:

下面我遇到奇怪问题的代码旨在修剪整数数组的未使用部分,然后将其转换为字符串。

例如: _ABC__DE______ 将变为 _ABC__DE

当输入用默认字符填充时,问题就会出现。 (示例中为“_”)。

sLength是整数数组chars的长度

有问题的代码:

  int inputLength = sLength - 1;

  while (chars[inputLength] == defaultChar && inputLength >= 0) {
    inputLength--;
  }

  inputLength++;

  Serial.println("input length: " + String(inputLength));
  // (in)sanity check
  Serial.println(inputLength);
  Serial.println(String(inputLength));
  Serial.println(inputLength <= 0);
  Serial.println(0 <= 0);
  Serial.println(inputLength == 0);
  Serial.println(0 == 0);

  if (inputLength <= 0) {
    //reset cursor position
    Serial.println("index set to 0");
    index = 0;
  } else {
    output = "";
    for (int i = 0; i < inputLength; i++) {
      char c = charSet[chars[i]];
      if (c == '_') {
        c = ' ';
      }
      output += c;
    }
    done = true;
  }

给定一个填充有defaultChar的数组时的输出:

input length: 0
0
0
0
1
0
1

如果我的解释正确,输出意味着偶数行上 0 > 0 和 0 =/= 0,但奇数行上 0


我想出的解决方法是替换

  while (chars[inputLength] == defaultChar && inputLength >= 0) {
    inputLength--;
  }

使用以下之一

  while (inputLength >= 0 && chars[inputLength] == defaultChar) {
    inputLength--;
  }

.

  while (chars[inputLength] == defaultChar) {
    inputLength--;
    if (inputLength < 0) {
      break;
    }
  }

两者都导致输出:

input length: 0
0
0
1
1
1
1
index set to 0

为什么这会改变结果? 据我目前所知,&& 运算符是可交换的。

有什么我错过的东西

chars[inputLength] == defaultChar &amp;&amp; inputLength &gt;= 0

不等于

inputLength &gt;= 0 &amp;&amp; chars[inputLength] == defaultChar?

如果相关,这是在 328P Arduino Nano 上运行,带有使用 IDE 1.8.8 的旧引导加载程序

【问题讨论】:

    标签: c++ arduino embedded logical-operators


    【解决方案1】:

    &amp;&amp; 不可交换。它首先计算左操作数,然后在左操作数计算为0 时停止。

    您的原始代码失败,因为在某些时候它会评估 chars[-1](如果 chars 是一个数组,则会导致 undefined behaviour)。替代版本没有这个问题,因为它在使用inputLength 作为数组索引之前执行&gt;= 0 测试。

    【讨论】:

      【解决方案2】:

      &amp;&amp; 是可交换的,因为a &amp;&amp; b 的结果与b &amp;&amp; a 的结果相同。但是内置运算符&amp;&amp; 有一个short-circuiting behavior。这意味着如果a &amp;&amp; b 的结果可以通过单独评估第一个操作数来决定,则不会评估第二个操作数。

      所以当第一个操作数是chars[inputLength] == defaultChar 并且inputLength-1 时,你进入了未定义行为的领域,这意味着程序的行为是不可预测的。但是通过这些变通方法,您可以避免由于inputLength &gt;= 0inputLength &lt; 0 检查而导致的未定义行为,因此代码可以按预期工作。

      正如@PeteBecker 所说:如果a()b() 有副作用,则a() &amp;&amp; b() 不可交换。

      【讨论】:

      • 如果a()b() 有副作用,您可能会提到a() &amp;&amp; b() 不可交换。
      • @PeteBecker:谢谢。将其添加到答案中。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-21
      • 1970-01-01
      相关资源
      最近更新 更多