c - 在 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
我错过的重点在哪里?位移部分有问题吗?
解决方案
在没有 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
推荐阅读
- vb.net - Visual Studio 中 datetimepicker 中的默认日期
- java - enum - 不能从非静态上下文中引用非静态方法
- java - 当凭据存储在主数据库中时,使用本地数据库在本地应用程序上对用户进行身份验证
- sql - 给定一个经度/纬度,将米转换为经度/纬度
- python-3.x - 将多个参数传递到 python urllib 模块
- android - 最小化全屏Android应用程序后状态栏重新出现
- vba - Outlook VBA 创建的草稿邮件在发送时出现“操作失败”错误
- python - 如何在 Pyspark 中创建一个虚拟(0 字节)HDFS 文件
- android - ConstraintLayout 内的 RecyclerView - 父级顶部的起始位置
- ruby - 如何解密在 Ruby 中使用 des 命令加密的文件?