&&运算符交换性质的问题

时间:2019-02-21 09:19:08

标签: c++ arduino embedded logical-operators

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

例如: _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 <= 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 && inputLength >= 0

不等于

inputLength >= 0 && chars[inputLength] == defaultChar

如果有意义的话,它可以在旧的引导加载程序上使用IDE 1.8.8在328P Arduino Nano上运行

2 个答案:

答案 0 :(得分:5)

&&不是可交换的。它首先评估左操作数,然后在左操作数评估为0时停止。

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

答案 1 :(得分:3)

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

因此,当第一个操作数为chars[inputLength] == defaultCharinputLength-1时,您将输入未定义行为的范围,这意味着程序的行为是不可预测的。但是有了变通办法,您就会由于inputLength >= 0inputLength < 0检查而避免未定义的行为,因此代码按预期工作。

@PeteBecker指出:如果a() && b()a()有副作用,则b()不可交换。

相关问题