gpt4 book ai didi

c++ - 将无符号(长)整数解释为在 C++ 中签名

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:08:36 26 4
gpt4 key购买 nike

我想将 unsigned long 的 32 位重新解释为 signed long。完全相同的位,只是被视为 2 的补码整数而不是无符号整数。我不认为简单地将它转换为 long 就可以解决问题。我错了吗?

或者也许有更好的方法。我正在使用 unsigned long 作为计时器。有时我会读取它的当前值并将其与之前的读数(均为 unsigned long)进行比较,以查看过去了多少时间。我需要处理可能的溢出,这会导致当前值小于以前的值。将两个值都解释为带符号的长整型并相减似乎给出了正确的答案。

我试过这个:

return reinterpret_cast<long>(time4) - reinterpret_cast<long>(currTimeLo); // treat unsigned as 2's complement

但刚刚得到一个编译器错误:

Arduino: 1.6.7 (Mac OS X), Board: "Arduino Nano, ATmega328"
invalid cast from type 'long unsigned int' to type 'long int'

最佳答案

关于通过比较两个无符号计数器来检查经过了多少时间的更深层次/原始问题,其中可能有 1 个单一环绕:

使用无符号算术简单地从最新的减去最早的。

假设您的 currTimeLo 是当前时间的计数器值,而 time4 是某个更早的值,并且它们都是无符号类型(或有符号类型之一类型提升了另一个的无符号类型),

return currTimeLo - time4;

这是因为 C++ 保证无符号算术以 2n 为模执行,其中 n 是值表示中的位数无符号类型。

在超过 1 个环绕的情况下,此方法将不起作用。在这种情况下,您需要使用具有更大数字范围的类型。


关于题名将无符号值解释为2的补码有符号值的问题:

首先请注意,这不是必需的。这是 X/Y 问题中的 Y。获取两个计数器之间的差异,最新的可能已经包装,是原始的 X,它有一个简单的解决方案(上图)。


但是,既然这是标题中的问题:

据我所知,所有现存的 C++ 实现都适用于有符号整数使用 2 的补码表示的体系结构。

当原始值无法用该类型表示时,Holy Standard™ 将其留给实现来定义转换为有符号整数类型的结果。任何合理的 C++ 实现都会让您通过 static_cast 来完成。因此,

return static_cast<long>(time4) - static_cast<long>(currTimeLo);

但是不能保证您在 Arduino 中的编译器在这方面是合理的。

你将不得不检查它,并在必要时使用相关选项,假设默认情况下不合理的行为可以调整。

解决方法包括

  • 通过reinterpret_cast 转换指针或引用,

  • 通过例如复制字节memcpy,形式上安全但复杂且不必要地可能效率低下,

  • 使用正式的 UB union 成员访问权限,或

  • 安全但复杂,拆分值并重新组合。

最后一点可以用一种近乎优雅的方式来完成,有人在 SO 上早先针对这个问题的语言律师变体发表了回应。不幸的是,我不记得那个把戏,只记得它给我留下了深刻的印象,因为它是如此明显,但却是我没有想到的。但我推荐经过适当测试的简单 static_cast

关于c++ - 将无符号(长)整数解释为在 C++ 中签名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35108622/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com