在 Arduino 中转换 signed/unsigned int 变量的问题

Problem with converting signed/unsigned int variables in Arduino

我正在制作一个电路,它将从 4011 移位寄存器中提取数据。到目前为止它工作正常,但是当我的数字超过某个值时,奇怪的事情开始发生。

此代码将循环我所有的 4011。

  typedef unsigned long u_long;

  for (u_long i = 0; i < 32; i++)
  {
    digitalWrite(CLOCK_in,0);
    delayMicroseconds(0.2);

    bool bit = digitalRead(DATA_in);

    Serial.print(bit,BIN);

    if (bit) out |= (1 << i); 

    digitalWrite(CLOCK_in,1);
  }
  Serial.println((u_long)out);
  Serial.println((u_long)out,BIN);

从第一个 "print()" 我得到:

00000000000000010000000000000000

这是我所期望的,因为这是我的输入(我的目标是将其转换为无符号长十进制 - 最高数字为 32 位)。从下一个 print() 开始,我得到 4294934528。我认为这是不正确的。从最后一个 print() 函数,天真的我期望得到与第一个相同的答案,我得到 11111111111111111000000000000000

我漏掉的地方在哪里? bitshift 部分有问题吗?

我在没有 MCVE 的情况下立即发现了一个问题

for (u_long i = 0; i < 32; i++)
{
    ...
    if (bit) out |= (1 << i);
    ...
}

在 Arduino 中 int 是 16 位类型,整数文字是 int type by default. Shifting by more than the bit width invokes undefined behavior,因此当 i > 15

时,您的代码有 UB

要修复该问题,请使用 L 后缀使其成为 long 文字

if (bit) out |= (1L << i);

但是没有理由在 Arduino 中使用慢速 32 位变量进行循环。只需使用 int,甚至更好 uint8_t。还可以将 uint32_t 与输出类型的标准 UINT32_C 宏一起使用,这样您就不需要计算出正确的后缀

uint32_t out;
for (int i = 0; i < 32; i++)
{
    ...
    if (bit) out |= UINT32_C(1) << i;
    ...
}

也就是说,您还需要提供 MCVE