我在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
有人可以解释为什么会这样吗?
答案 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_t
或int32_t
来获取已定义大小的整数。
编辑:使用函数参数遵循与上述初始化者基本相同的原则。
更新:正如您所说,当直接将整数常量86400
传递给函数时,它将具有类型long
,因为编译器将自动选择可以保存值的最小类型。 println
参数很可能超出long
方法,因此它们将打印正确的值。
但是,对于表达式,原始类型是相关的。并且所有值24
,60
,60
都将具有int
类型,因此结果也将为int
。编译器不会使用更大的类型,只是因为结果可能溢出。使用24L
,您也会获得宏的long
结果。
答案 2 :(得分:0)
20864 = 86400%65536
尝试将值存储在int而不是short。