什么是C中的算术下溢和溢出?

算术下溢和溢出在C编程中意味着什么?

溢出

来自http://en.wikipedia.org/wiki/Arithmetic_overflow :

当计算产生的结果大于给定寄存器或存储位置可以存储或表示的结果时发生的条件。

所以,例如:

uint32_t x = 1UL << 31; x *= 2; // Overflow! 

请注意,正如@R在下面的评论中提到的那样,C标准建议:

涉及无符号操作数的计算永远不会溢出,因为无法通过生成的无符号整数类型表示的结果将以比结果类型可以表示的最大值大1的数量为模。

当然,这是“溢出”的一个相当特殊的定义。 大多数人会将模数减少(即环绕)称为“溢出”。

潜流

来自http://en.wikipedia.org/wiki/Arithmetic_underflow :

当浮点运算的真实结果的幅度(​​即,接近于零)小于目标数据类型中可表示为正常浮点数的最小值时,可能发生的计算机程序中的条件。

所以,例如:

 float x = 1e-30; x /= 1e20; // Underflow! 

计算机仅使用0和1来表示数据,以便可以表示的值范围受到限制。 许多计算机使用32位来存储整数,因此在这种情况下可以存储的最大无符号整数是2 ^ 32 -1 = 4294967295.但是第一位用于表示符号,因此,实际上,最大值是2 ^ 31 – 1 = 2147483647。

超出允许范围的整数需要比可存储的位多的位的情况称为溢出。

类似地,对于实数,指数太小而无法存储会导致下溢。

int,C中最常见的数据类型,是32位数据类型。 这意味着每个in​​t在内存中被赋予32位。 如果我有变量

 int a = 2; 

它实际上将在内存中表示为32位二进制数:00000000000000000000000000000010。

如果你有两个二进制数,如

10000000000000000000000000000000

10000000000000000000000000000000,

它们的总和将是100000000000000000000000000000000,这是33位长。 但是,计算机只占用32个最低有效位,它们都是0.在这种情况下,计算机识别出总和大于32位存储的总和,并给出溢出错误。

下溢基本上是相反方向发生的事情。 用于C的浮点标准允许小数点后的23位; 如果数字的精度超过此点,则无法存储这些位。 这导致下溢误差和/或精度损失。

下溢完全取决于给定的算法和给定的输入数据,因此程序员没有直接控制。另一方面,溢出取决于程序员对每个堆栈保留的内存空间量的任意选择,以及这种选择确实会影响溢出的次数