为什么整数溢出未定义行为仅适用于有符号整数,而不适用于无符号整数?
使有符号整数溢出未定义行为的目的是允许编译器优化。但这不是使无符号整数溢出也成为未定义行为的同样有效的参数吗?
回答
保持有符号整数溢出未定义的目的可能是编译器优化1。但最初的原因是标准没有定义有符号整数的位表示。不同的实现提供了不同的有符号整数表示,它们的溢出特性也会不同。这只是允许的,因为标准没有定义这些溢出特性是什么。
相比之下,无符号整数位表示总是明确定义的(否则,您无法有效地执行大量按位运算),因此它们的溢出行为也可以明确定义。
特定大小的无符号整数的布尔运算,在该值表示下,以最大无符号值 + 1 为模工作。因此,标准有一种方法可以说明任何数学运算的结果:它是对最大无符号值 + 1。
也就是说,如果你有一个 65535 的 16 位无符号整数,并给它加 1,则数字结果是 65536。但是,你在 16 位数字中得到的结果是 0。这是标准定义的,因为这就是布尔运算对特定位深度的工作方式。表示定义了行为。
相比之下,不同的有符号整数形式具有不同的溢出特性。如果标准在 16 位有符号整数中定义了 32767 + 1 的特定含义,那么如果特定的有符号整数表示不能自然地提供该答案,则编译器将不得不更改它添加这些值以产生该答案的方式。对于有符号/数量级,此加法结果为 -0。如果标准使实际行为成为现实,那么每两个补码实现将无法仅添加数字。它必须检查溢出并伪造结果。
在每个数学运算上。
1还有其他原因,例如大多数代码不能容忍它被定义得那么好。这是大多数有符号整数溢出的代码,如果它是明确定义的