在#define 内相乘给出奇怪的值
Multiplying within #define gives strange values
我为 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 Comunity 和 vMicro
您使用整数文字来定义您的值,并且如 documentation type of literal depends on where it can fit. According to specs
中所述
On the Arduino Uno (and other ATmega based boards) an int stores a 16-bit (2-byte) value.
(重点是我的)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);
或按照之前的建议使用后缀。
我为 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 Comunity 和 vMicro
您使用整数文字来定义您的值,并且如 documentation type of literal depends on where it can fit. According to specs
中所述On the Arduino Uno (and other ATmega based boards) an int stores a 16-bit (2-byte) value.
(重点是我的)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);
或按照之前的建议使用后缀。