使用Microchip 18f4620 PIC。不过,这应该是标准的ANSI C问题。
说我有
unsigned int16 badFlow=65535 //max unsigned int16 value
二进制值为1111 1111 1111 1111
。
如果我那么
badFlow++;
位模式变为1 0000 0000 0000 0000
17位。显然是badFlow == 0
,但是额外的翻转位
byte* flowPtr = &badFlow+2;
的任何地方
分。我假设后者,但希望前者。
我的问题:一位同事用一个计数器写了一些不好的代码,这些计数器已经在所有生产的产品上溢出了大约2年。考虑到我们的客户对这些工具的使用收费,由于潜在的不良数据而导致数百万美元的危险。
答案 0 :(得分:7)
C中的算术使用值进行,而不是内存中的字节。您的表达式badFlow++
相当于badFlow = badFlow + 1
。右侧被评估为类型int
(由于默认促销,假设int
大于16位;如果int
仅为16位,那么它将被评估为{{ 1}})导致65536,然后当65536被分配到无符号的16位变量时,它以模数65536减少,结果为0.
摆脱这个答案的重要一点是unsigned int
不是对badFlow++
内存的直接操作(尽管它可能实现 on on一些实现)。它只是添加和赋值的简写。
答案 1 :(得分:5)
最重要的数字被丢弃。许多处理器都有一个状态寄存器,指示发生溢出,但是从C中看不到(你必须在汇编中使用它才能使用它)
答案 2 :(得分:4)
不会溢出到badFlow
后面的内存中。
答案 3 :(得分:4)
选项1是正确的,溢出被静默丢弃。
答案 4 :(得分:4)
在标准C中溢出或下溢整数类型通常是安全的操作,并且不会修改超出所访问变量范围的内存。在标准C中,溢出位被丢弃,但实现可以将其存储在特殊的溢出寄存器或专用存储器位置。例如,在i386系统上,溢出信号在“进位标志”中发出信号。
编辑:正如@aix指出的那样,每个相关的i386汇编指令都不会更新进位标志。这当然是一个实施细节; C语言没有给出两个关于进位标志的声音。
编辑2 :正如R.指出的那样,签名溢出是未定义的行为,尽管我看到的每个实现仍然安全地对待它。
答案 5 :(得分:0)
转移到uint32
并发布新软件将是正确的方法..