Arduino 无符号长溢出
Arduino unsigned long overflow
我正在尝试了解 Arduino C++ 的溢出条件(特别是 Due/SAM3X8E),以便编写基于 micros() 函数的定时器逻辑。
对于那些不知道的人,Arduino micros() 函数 returns 自程序启动以来经过的微秒数,作为 32 位无符号长。此值将每 2^32 微秒(约 71 分钟)换行。
问题是我在 GCC 中看到的结果与我在在线 arduino 模拟器上看到的结果不同。
这是我的测试代码——首先是 GCC 版本:
#include <stdio.h>
int main()
{
unsigned long currentTime = 0x00000100;
unsigned long earlierTime = 0xFFFFFF00;
unsigned long result = currentTime-earlierTime;
printf("%lx", result);
return 0;
}
上面的设置是通过在结果变量中产生负数来使值溢出,并且 returns 十六进制 ffffffff00000200,如我所料。
但是 Arduino:
// setup
unsigned long currentTime = 0x00000100;
unsigned long earlierTime = 0xFFFFFF00;
// main loop
unsigned long result = currentTime-earlierTime;
运行 在线 arduino sim wokwi returns (hex) 200,这不是预期的,但实际上对我更有用,因为我的计时器检查仍然有效micros() 输出每 71 分钟回零一次。
所以我的问题是:为什么行为会有所不同?我是否可以相信在线 Arduino 模拟器表现出的行为与 Arduino Due(模拟器基于 Uno)相同?我目前没有真正的 Due 硬件来测试。
我希望这个问题对某人有意义。
Arduino 上的 unsigned long 有 32 位,因此模拟器正在执行我期望实际 Arduino 执行的操作。
在台式机上,unsigned long 可以是 32 位或 64 位,具体取决于操作系统、硬件和编译器。
您的 gcc 测试中的 printf 显示了一个 64 位值,因此在您的平台上,这些无符号长整型似乎有 64 位。由于这与您在 Arduino 上获得的不同,因此获得不同的结果也就不足为奇了。对于各自的平台,这两个结果看起来都是正确且一致的,所以我不确定混淆在哪里。
几乎所有 C 和 C++ 平台都可以让您在需要时获得恰好 32 位无符号整数:
- 在 C 中,您包含
<stdint.h>
并使用类型 uint32_t
。
- 在 C++ 中,您包含
<cstdint>
并使用类型 std::uint32_t
。
如果您相应地修改您的代码示例,无论您是在桌面上还是在 Arduino(或模拟器)上使用代码,您都应该得到一致的结果。
我正在尝试了解 Arduino C++ 的溢出条件(特别是 Due/SAM3X8E),以便编写基于 micros() 函数的定时器逻辑。
对于那些不知道的人,Arduino micros() 函数 returns 自程序启动以来经过的微秒数,作为 32 位无符号长。此值将每 2^32 微秒(约 71 分钟)换行。
问题是我在 GCC 中看到的结果与我在在线 arduino 模拟器上看到的结果不同。
这是我的测试代码——首先是 GCC 版本:
#include <stdio.h>
int main()
{
unsigned long currentTime = 0x00000100;
unsigned long earlierTime = 0xFFFFFF00;
unsigned long result = currentTime-earlierTime;
printf("%lx", result);
return 0;
}
上面的设置是通过在结果变量中产生负数来使值溢出,并且 returns 十六进制 ffffffff00000200,如我所料。
但是 Arduino:
// setup
unsigned long currentTime = 0x00000100;
unsigned long earlierTime = 0xFFFFFF00;
// main loop
unsigned long result = currentTime-earlierTime;
运行 在线 arduino sim wokwi returns (hex) 200,这不是预期的,但实际上对我更有用,因为我的计时器检查仍然有效micros() 输出每 71 分钟回零一次。
所以我的问题是:为什么行为会有所不同?我是否可以相信在线 Arduino 模拟器表现出的行为与 Arduino Due(模拟器基于 Uno)相同?我目前没有真正的 Due 硬件来测试。
我希望这个问题对某人有意义。
Arduino 上的 unsigned long 有 32 位,因此模拟器正在执行我期望实际 Arduino 执行的操作。
在台式机上,unsigned long 可以是 32 位或 64 位,具体取决于操作系统、硬件和编译器。
您的 gcc 测试中的 printf 显示了一个 64 位值,因此在您的平台上,这些无符号长整型似乎有 64 位。由于这与您在 Arduino 上获得的不同,因此获得不同的结果也就不足为奇了。对于各自的平台,这两个结果看起来都是正确且一致的,所以我不确定混淆在哪里。
几乎所有 C 和 C++ 平台都可以让您在需要时获得恰好 32 位无符号整数:
- 在 C 中,您包含
<stdint.h>
并使用类型uint32_t
。 - 在 C++ 中,您包含
<cstdint>
并使用类型std::uint32_t
。
如果您相应地修改您的代码示例,无论您是在桌面上还是在 Arduino(或模拟器)上使用代码,您都应该得到一致的结果。