微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在#define 中相乘会给出奇怪的值

如何解决在#define 中相乘会给出奇怪的值

我为 Arduino Nano 编写了一个代码,但我遇到了这种奇怪的行为:

#define     GREAT      (60 * 60000)
#define     STRANGE     (60 * 6000)
#define     ZERO_X      (60 * 1000)

void setup() {
    Serial.begin(115200);
    Serial.println(GREAT);      // Prints 3600000,that's correct
    Serial.println(STRANGE);    // Prints 32320,thats wrong
    long zerox = ZERO_X;
    Serial.println(zerox);      // Prints -5536,thats also wrong,obvIoUsly
}

void loop() {}

这是怎么回事?

我将 MSVS2019 社区与 vMicro 一起使用

解决方法

您使用整数文字来定义您的值,如 documentation 中所述,文字类型取决于它可以适合的位置。根据{{​​3}}

在 Arduino Uno(和其他基于 ATmega 的电路板)上,一个 int 存储一个 16 位(2 字节)值。

(重点是我的)Arduino Nano 的 CPU 有 2 个字节 int - 6060001000 适合有符号整数,并且使用这种类型。尽管 60 * 600060 * 1000 的值都不能容纳 2 个字节 int,因此您会因 UB 和意外值而导致整数溢出。

另一方面,60000 不适合 2 个字节的 signed int,因此它获得类型为 long 的 4 个字节和 60000 * 60 适合那里,因此您得到预期的结果。要解决您的问题,您只需指定后缀:

#define     GREAT      (60 * 60000L)
#define     STRANGE     (60 * 6000L)
#define     ZERO_X      (60 * 1000L)

并强制它们全部输入 long。没有必要为 60000 执行此操作,但为了一致性最好使用它。

对于您的代码更改:

long zerox = ZERO_X;

这一行没有解决问题,因为宏替换后它等于:

long zerox = (60 * 1000);

并且它没有帮助,因为类型为 int 的第一次计算是在初始化的右侧完成的,溢出发生,然后 int 被提升为 long。要修复它,您需要将参数之一转换为 long:

 long zerox = 60 * static_cast<long>(1000);

或使用之前建议的后缀。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。