【发布时间】:2011-09-15 15:30:58
【问题描述】:
C 编程中算术下溢和上溢是什么意思?
【问题讨论】:
标签: c math integer-overflow
C 编程中算术下溢和上溢是什么意思?
【问题讨论】:
标签: c math integer-overflow
溢出
来自http://en.wikipedia.org/wiki/Arithmetic_overflow:
当一个 计算产生的结果是 在幅度上大于一个 给定的寄存器或存储位置可以 存储或代表。
例如:
uint32_t x = 1UL << 31;
x *= 2; // Overflow!
请注意,正如@R 在下面的评论中提到的,C 标准建议:
涉及无符号的计算 操作数永远不会溢出,因为 无法表示的结果 得到的无符号整数类型是 减少模数是一 大于最大值 可以用结果来表示 输入。
当然,这是“溢出”的一个相当特殊的定义。大多数人会将模减少(即环绕)称为“溢出”。
下溢
来自http://en.wikipedia.org/wiki/Arithmetic_underflow:
计算机程序中的条件 当一个真正的结果可能会发生 浮点运算在 幅度(即接近于零) 比可表示的最小值 作为一个普通的浮点数 目标数据类型。
例如:
float x = 1e-30;
x /= 1e20; // Underflow!
【讨论】:
unsigned char x = 0; x -= 1; 呢?这算不算下溢?
计算机只使用 0 和 1 来表示数据,因此可以表示的值的范围是有限的。很多计算机使用32位来存储整数,所以这种情况下可以存储的最大无符号整数是2^32 -1 = 4294967295。但是第一位是用来表示符号的,所以,其实最大值是2^31 - 1 = 2147483647。
超出允许范围的整数需要的位数超过可存储的位数的情况称为溢出。
同样,对于实数,指数太小而无法存储会导致下溢。
【讨论】:
int 是 C 语言中最常见的数据类型,是 32 位数据类型。这意味着每个 int 在内存中都有 32 位。如果我有变量
int a = 2;
这实际上会在内存中表示为 32 位二进制数: 000000000000000000000000000000010.
如果你有两个二进制数比如
100000000000000000000000000000000
和
100000000000000000000000000000000,
它们的总和将是 100000000000000000000000000000000,即 33 位长。但是,计算机只取了 32 个最低有效位,它们全为 0。在这种情况下,计算机识别出总和大于 32 位可以存储的值,并给出溢出错误。
下溢基本上是在相反方向发生的相同事情。 C 使用的浮点标准允许小数点后 23 位;如果数字的精度超过这一点,它将无法存储这些位。这会导致下溢错误和/或精度损失。
【讨论】:
int 不是 32 位数据类型。
下溢完全取决于给定的算法和给定的输入数据,因此程序员没有直接控制。另一方面,上溢取决于程序员为每个人保留的内存空间量的任意选择堆栈,并且此选择确实会影响可能发生溢出的次数
【讨论】: