#define在C中返回错误的数字

时间:2015-11-25 00:06:17

标签: arduino

我在C中尝试这个非常基本的任务,我想在头文件中定义一些int。我是这样做的:

#define MINUTE (60)
#define HOUR   (60 * MINUTE)
#define DAY    (24 * HOUR)

问题是,当MINUTE和HOUR返回正确的答案时,DAY会返回一些奇怪的东西。

Serial.println(MINUTE); // 60
Serial.println(HOUR); // 3600
Serial.println(DAY); // 20864

有人可以解释为什么会这样吗?

3 个答案:

答案 0 :(得分:4)

看起来你真的设法挖掘了一个古老的16位编译器(你在哪里找到它?)否则我希望看到产生这些数字的代码。

答案 1 :(得分:4)

假设您有类似

的内容
int days = DAY;

unsigned days = DAY;

你似乎有16位整数。最大(带符号)2s补码整数16位的可表示正值为32767,无符号则为65535。

因此,作为24 * 3600 == 86400,您为已签名的int调用未定义的行为并为unsigned进行换行(int也可能会换行,但这不是保证)。

这导致86400 modulo 65356(16的幂为2)恰好是20864

解决方案:使用stdint.h类型:uint32_tint32_t来获取已定义大小的整数。

编辑:使用函数参数遵循与上述初始化者基本相同的原则。

更新:正如您所说,当直接将整数常量86400传递给函数时,它将具有类型long,因为编译器将自动选择可以保存值的最小类型。 println参数很可能超出long方法,因此它们将打印正确的值。

但是,对于表达式,原始类型是相关的。并且所有值246060都将具有int类型,因此结果也将为int。编译器不会使用更大的类型,只是因为结果可能溢出。使用24L,您也会获得宏的long结果。

答案 2 :(得分:0)

20864 = 86400%65536

尝试将值存储在int而不是short。