在C语言中,算术下溢和上溢是什么?

24

C编程中的算术下溢和上溢是什么意思?

4个回答

37

溢出

来源于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!

6
在C标准语言中,你关于溢出的例子是错误的。无符号类型不能发生溢出 - R.. GitHub STOP HELPING ICE
2
@R.:“溢出”这个词在C标准之外也有一个被广泛理解的含义!但你说得对,我会在我的答案中包含这个事实。 - Oliver Charlesworth
这种区别在人们说“整数溢出总是导致未定义行为”之类的话时非常重要。 - R.. GitHub STOP HELPING ICE
unsigned char x = 0; x -= 1; 这算作下溢吗? - Gamal Othman
1
我在Wikipedia上发现这被称为“整数溢出”或“整数环绕”。它说:请注意,将值存储在整数变量中时(例如尝试在无符号整数中存储-1),正确地称为整数溢出,或更广泛地称为“整数环绕”。术语下溢通常仅适用于浮点数,并且是一个单独的问题。谢谢! - Gamal Othman

8
计算机只使用0和1来表示数据,因此可以表示的值的范围是有限的。许多计算机使用32位来存储整数,因此在这种情况下可以存储的最大无符号整数是2^32 - 1 = 4294967295。但第一位用于表示符号,因此实际上最大值是2^31 - 1 = 2147483647。
当整数超出允许范围时需要存储更多位数的情况称为溢出。
同样,对于实数,过小以至于无法存储的指数会导致下溢。

-4

int是C语言中最常见的数据类型,它是一个32位的数据类型。这意味着每个int在内存中被分配了32位。如果我有一个变量

int a = 2;

在内存中,一个32位的二进制数可以表示为:00000000000000000000000000000010。

如果你有两个二进制数:

10000000000000000000000000000000

10000000000000000000000000000000,

它们的和将是100000000000000000000000000000000,长度为33位。然而,计算机只取最低的32位,其余的都是0。在这种情况下,计算机认为和大于32位所能存储的范围,会出现溢出错误。

下溢基本上是相反方向发生的同样事情。C语言使用的浮点标准允许小数点后保留23位;如果数字的精度超过了这个范围,它将无法存储这些位。这会导致下溢错误和/或精度损失。


一台计算机通常没有检查操作是否导致溢出。你从哪里得到的23? - Oliver Charlesworth
1
int 不是一个32位数据类型。 - Philip
根据IEEE 754标准,单精度浮点数具有23位有效数字(不是位数)。还有一个隐含的位通常会给你24位的精度,但在下溢期间不适用,这时使用次正规数提供逐渐丧失精度的过程。 - Michael Carman
@Oli Charlesworth:通常每个CPU都在其状态寄存器中有一个溢出标志。(也许你的意思是C语言对此不关心) - Curd
@Curd:是的,我现在也记不起当时的意思了!希望我的意思是你不能从C中访问状态标志。 - Oliver Charlesworth
显示剩余2条评论

-5

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


1
你把算术下溢和堆栈溢出搞混了,还把它们放在一起,这样做让你的回答最多只会令人困惑。我也不确定我赞同你的定义。 - bolov
你的回答只说了它们之间的区别,但没有说明它们是什么;问题的标题是“什么是下溢和上溢”。 - GingerPlusPlus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接