Answers:
每当您用C / C ++编写方程式时,要操作的数据类型都会对方程式的输出产生非常实际的影响。
每种类型(例如int
,float
和)unsigned long
都有不同的行为,并占用一定的内存空间来存储。
int
(在arduino上)存储为16位,其中一半的值提供给负数,一半的值提供给正值,一个值提供给0。这使其范围为-2 ^ 15(-32,768)到+ 2 ^ 15-1(32,767)。
unsigned long
(在arduino上)为32位,但没有一个被指定为负数。那么其范围是0到2 ^ 32-1(4294967295)。
什么样的数学?与Millis一起工作时,排除了哪种其他类型的处理?
问题的症结在于,毫秒返回的时间超过了32767,而您试图将其存储在int中,arduino无法做到这一点,因为int
不能容纳这么多的数字。数学类型超出范围是数学发生在较小的数据类型上,而不是任何特定的运算。也许这些例子会有所帮助:
int i = 32767;
Serial.println(i);
//No problems here; it fits just fine
32767
i = 32767 + 1;
Serial.println(i);
//Oh no, the value didn't fit
-32768
unsigned long fake_millis = 42000;
i = fake_millis;
Serial.println(i);
//This is an example of millis going past an int
-23536
i = -10;
unsigned int j = i;
Serial.println(j);
//no way to put a negative number in an unsigned value
65526
uint32_t k = fake_millis;
Serial.println(k);
//unsigned long is a uint32_t on arduino; this works great!
42000
这种实现的方式确实很天才。如果您对这些数字的来源以及它们为什么以这种方式溢出感兴趣,您应该研究一下关于补数数字表示形式的相同解释。
unsigned long
可以随不同平台(例如x86)而变化,uint32_t
到处总是32个无符号位。
32767 + 1
)产生未定义的行为,这几乎总是一件坏事。您的其他示例是您可以依靠的已记录行为。
millis()
返回unsigned long
,这是Arduino上的32位无符号整数。然后,当您尝试执行类似操作时unsigned int time = millis() - 1000
,您尝试将其存储在16位无符号整数中unsigned int
。16位整数永远不能保存32位值。
根据C规范第6.3.1.3段,高16位被丢弃。
如果可能的话,请将millis()
输出保留在中,unsigned long
并且在绝对确定不会丢失位的情况下仅使用位数较少的数据类型。
有关C中显式强制转换的更多信息,请访问:https://stackoverflow.com/a/13652624/1544337
uint32_t
恰好是unsigned long
arduino的返回值更正确吗?
unsigned long
。
int time = millis() - 1000
),则结果类似:丢弃高16位。这次,C标准说结果是实现定义的,并且行为在gcc文档中指定了实现定义的整数行为(第四个要点)。