首页 > 解决方案 > 在 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(),howeer,我得到4294934528。我认为这是不正确的。从最后一个print()函数中,我天真地期望与第一个函数相同的答案,我得到11111111111111111000000000000000

我错过的重点在哪里?位移部分有问题吗?

标签: carduinobit-shift

解决方案


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

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

在 Arduinoint中是 16 位类型,而整型字面量是int默认类型。移位超过位宽会调用未定义的行为,因此当 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


推荐阅读