3

使用 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,但额外的翻转位要么

  1. 被丢弃
  2. 或居住在任何地方byte* flowPtr = &badFlow+2;

我假设后者,但希望前者。

我的问题:一位同事用计数器编写了一些错误的代码,该计数器已在所有生产的产品上溢出约 2 年。考虑到我们的客户对使用这些工具的收费,由于潜在的不良数据,这将带来几百万美元的风险。

4

6 回答 6

7

C 中的算术运算发生在,而不是内存中的字节。你的表达badFlow++相当于badFlow = badFlow + 1。右侧被评估为类型int(由于默认提升,假设int大于 16 位;如果int只有 16 位,则将其评估为unsigned int)导致 65536,然后将 65536 分配给无符号 16 位变量,它以 65536 为模减少,结果为 0。

摆脱这个答案的重要一点是,这badFlow++不是对内存的直接操作&badFlow(尽管它可能在某些实现中这样实现)。它只是添加和分配的简写。

于 2012-01-09T18:41:23.323 回答
5

最重要的数字被丢弃。许多处理器都会有一个状态寄存器来指示发生了溢出,但这在 C 中是不可见的(你必须在汇编中工作才能使用它)

于 2012-01-09T18:30:45.207 回答
4

不会溢出到后面的内存中badFlow

于 2012-01-09T18:29:41.480 回答
4

选项1是正确的,溢出被默默丢弃。

于 2012-01-09T18:30:34.317 回答
4

标准 C 中的整数类型上溢或下溢通常是一种安全操作,并且不会修改超出被访问变量范围的内存。在标准 C 中,溢出位被丢弃,尽管实现可能将其存储在特殊的溢出寄存器或专用内存位置。例如,在 i386 系统上,溢出在“进位标志”中发出信号。

编辑:正如@a​​ix 指出的那样,每个相关的 i386 汇编指令都不会更新进位标志。这当然是一个实现细节;C 语言并没有对进位标志进行两次抨击。

编辑 2:正如 R. 指出的那样,有符号溢出是未定义的行为,尽管我见过的每个实现仍然安全地对待它。

于 2012-01-09T18:31:09.277 回答
0

迁移到uint32并制作新的软件版本将是正确的方法。

于 2012-01-09T18:32:07.717 回答