左移 << 如何在不同的函数中给出不同的结果?
How can shift left << give different results in different functions?
我一直在调试 C++ 库中的问题,发现 文字 0 和 变量设置为 0 之间存在奇怪的区别但仅在图书馆内。如果我将代码复制到我自己的代码中,它会按预期工作。
库代码正在将 1
向下移动一个长整数以一次屏蔽掉一位。当发送某个代码(REPEAT 键)时,您发送了一种虚拟数据包,并且 "no bits" 因此它传输 headers 而没有数据。我假设 for-loop 如果没有要发送的位会跳过循环。
我已将其简化以分解作业,并添加了以下调试。我只是重复 nbits
和我添加的文字 0
的步骤。
void IRsend::sendNEC (unsigned long data, int nbits){
Serial.println(data, HEX);
Serial.print(" nbits = ");
Serial.println( nbits);
if(nbits == 0) Serial.println("nbits == 0"); else Serial.println("nbits != 0 ");
Serial.print(" 0 - 1 = ");
Serial.println(0 - 1);
Serial.print(" nbits - 1 = ");
Serial.println(nbits - 1);
Serial.print(" (1UL << (0 - 1) = ");
Serial.println(1UL << (0 - 1));
Serial.print(" (1UL << (nbits - 1) = ");
Serial.println(1UL << (nbits - 1));
...
// the part I was originally debugging:
for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) {
...
}
called like:
irsend.sendNEC(0xFFFFFFFF, 0);
这令人惊讶地给出了以下输出:
FFFFFFFF
nbits = 0
nbits == 0
0 - 1 = -1
nbits - 1 = -1
(1UL << (0 - 1) = 0
(1UL << (nbits - 1) = 1
最后两个结果怎么会不一样呢? nbit
是 0,那么当它们都以 -1 结束时,为什么文字 0 的偏移不同(我添加了额外的括号以确保)?
以及为什么,当我将完全相同的调试代码复制到调用该库的代码中,并调用如下测试函数时:
void runtest(unsigned long data, int nbits){
/// same debug ...
}
void setup() {
runtest(0xFFFFFFFF, 0);
}
我得到了预期的输出:
-- Same test again --
FFFFFFFF
nbits = 0
nbits == 0
0 - 1 = -1
nbits - 1 = -1
(1UL << (0 - 1) = 0
(1UL << (nbits - 1) = 0
我只能准确地猜测 0 == 0,例如如果它默认为更长的类型 0?
这是使用 Arduino IRRemote 库:https://github.com/z3t0/Arduino-IRremote/blob/master/ir_NEC.cpp
其 运行 在 ATmega328 上,我在 MacOSX 上构建,大概是在 Arduino 1.8.10 avr-gcc IDE.
来自 C++ 标准草案 expr.shift:
The operands shall be of integral or unscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater than or equal to the width of the promoted left operand.
您的代码有未定义的行为,所以任何事情都有可能发生。
... if the value of the right operand is negative or is greater or equal to the number of bits in the promoted left operand, the behavior is undefined
[强调我的]
不允许负偏移,这是未定义的行为。
我一直在调试 C++ 库中的问题,发现 文字 0 和 变量设置为 0 之间存在奇怪的区别但仅在图书馆内。如果我将代码复制到我自己的代码中,它会按预期工作。
库代码正在将 1
向下移动一个长整数以一次屏蔽掉一位。当发送某个代码(REPEAT 键)时,您发送了一种虚拟数据包,并且 "no bits" 因此它传输 headers 而没有数据。我假设 for-loop 如果没有要发送的位会跳过循环。
我已将其简化以分解作业,并添加了以下调试。我只是重复 nbits
和我添加的文字 0
的步骤。
void IRsend::sendNEC (unsigned long data, int nbits){
Serial.println(data, HEX);
Serial.print(" nbits = ");
Serial.println( nbits);
if(nbits == 0) Serial.println("nbits == 0"); else Serial.println("nbits != 0 ");
Serial.print(" 0 - 1 = ");
Serial.println(0 - 1);
Serial.print(" nbits - 1 = ");
Serial.println(nbits - 1);
Serial.print(" (1UL << (0 - 1) = ");
Serial.println(1UL << (0 - 1));
Serial.print(" (1UL << (nbits - 1) = ");
Serial.println(1UL << (nbits - 1));
...
// the part I was originally debugging:
for (unsigned long mask = 1UL << (nbits - 1); mask; mask >>= 1) {
...
}
called like:
irsend.sendNEC(0xFFFFFFFF, 0);
这令人惊讶地给出了以下输出:
FFFFFFFF
nbits = 0
nbits == 0
0 - 1 = -1
nbits - 1 = -1
(1UL << (0 - 1) = 0
(1UL << (nbits - 1) = 1
最后两个结果怎么会不一样呢? nbit
是 0,那么当它们都以 -1 结束时,为什么文字 0 的偏移不同(我添加了额外的括号以确保)?
以及为什么,当我将完全相同的调试代码复制到调用该库的代码中,并调用如下测试函数时:
void runtest(unsigned long data, int nbits){
/// same debug ...
}
void setup() {
runtest(0xFFFFFFFF, 0);
}
我得到了预期的输出:
-- Same test again --
FFFFFFFF
nbits = 0
nbits == 0
0 - 1 = -1
nbits - 1 = -1
(1UL << (0 - 1) = 0
(1UL << (nbits - 1) = 0
我只能准确地猜测 0 == 0,例如如果它默认为更长的类型 0?
这是使用 Arduino IRRemote 库:https://github.com/z3t0/Arduino-IRremote/blob/master/ir_NEC.cpp
其 运行 在 ATmega328 上,我在 MacOSX 上构建,大概是在 Arduino 1.8.10 avr-gcc IDE.
来自 C++ 标准草案 expr.shift:
The operands shall be of integral or unscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater than or equal to the width of the promoted left operand.
您的代码有未定义的行为,所以任何事情都有可能发生。
... if the value of the right operand is negative or is greater or equal to the number of bits in the promoted left operand, the behavior is undefined
[强调我的]
不允许负偏移,这是未定义的行为。