【问题标题】:Arduino unsigned long overflowArduino无符号长溢出
【发布时间】:2021-07-20 02:26:41
【问题描述】:

我正在尝试了解 Arduino C++(特别是 Due/SAM3X8E)的溢出条件,以便基于 micros() 函数编写定时器逻辑。

对于那些不知道的人,Arduino micros() 函数返回自程序启动以来经过的微秒数,为 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;
}

上面的设置是通过在结果变量中产生一个负数来使值溢出,并返回十六进制 ffffffff00000200,正如我所期望的那样。

但是在Arduino:

// setup
unsigned long currentTime = 0x00000100;
unsigned long earlierTime = 0xFFFFFF00;

// main loop
unsigned long result = currentTime-earlierTime;

在在线 arduino sim wokwi 上运行它会返回(十六进制)200,这是意料之外的,但实际上对我更有用,因为当 micros() 输出每 71 分钟归零时,我的计时器检查仍然有效。

所以我的问题是:为什么会有不同的行为?我可以依赖在线 Arduino 模拟器表现出的行为与 Arduino Due 相同(模拟器基于 Uno)吗?目前我没有真正的 Due 硬件可供测试。

我希望这个问题对某人有意义。

【问题讨论】:

  • 那么你想知道为什么有些在线模拟器会给出不同的结果吗?你在比较两个不同的部分,谁知道模拟器是否准确?

标签: arduino long-integer unsigned


【解决方案1】:

Arduino 上的 unsigned long 有 32 位,所以模拟器正在做我期望实际 Arduino 做的事情。

在台式电脑上,无符号长整数可以是 32 位或 64 位,具体取决于操作系统、硬件和编译器。

您的 gcc 测试中的 printf 显示了一个 64 位的值,因此在您的平台上,那些无符号长整数似乎有 64 位。由于这与您在 Arduino 上得到的不同,因此得到不同的结果也就不足为奇了。对于各自的平台,这两个结果看起来都是正确且一致的,所以我不确定哪里有混淆。

几乎所有 C 和 C++ 平台都可以让您获得所需的 32 位无符号整数:

  • 在 C 中,您包含 &lt;stdint.h&gt; 并使用类型 uint32_t。
  • 在 C++ 中,包含 &lt;cstdint&gt; 并使用类型 std::uint32_t。

如果您相应地修改代码示例,无论您是在台式机还是 Arduino(或模拟器)上使用代码,都应该得到一致的结果。

【讨论】:

  • 谢谢!这就是我所缺少的——操作系统是 64 位的,所以 int 类型是 64 位的。使用 32 位进行测试会得到与 uno/due 相同的结果。
  • @DavidBrandorf int 类型很少是 64b 宽。大多数 64b 平台的编译器都是 I32LP64(int 32b,long+pointers 64b)
猜你喜欢
  • 2016-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-10
  • 2012-02-29
  • 1970-01-01
  • 2011-04-23
  • 2020-06-07
相关资源
最近更新 更多