如何解决在#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
- 60
、6000
和 1000
适合有符号整数,并且使用这种类型。尽管 60 * 6000
和 60 * 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 举报,一经查实,本站将立刻删除。