C整数溢出

我正在使用C中的整数,试图更多地探讨溢出何时以及如何发生。

我注意到当我添加两个正数时,其总和溢出,我总是得到一个负数。

另一方面,如果我添加两个负数,其总和溢出,我总是得到一个正数(包括0)。

我做了一些实验,但我想知道这是否适用于每一个案例。

整数溢出是C中未定义的行为。

C表示涉及整数溢出的表达式,如果在通常的算术转换之后的结果是带符号的类型,并且不能在结果的类型中表示。 赋值和强制转换表达式是一个例外,因为它们由整数转换来控制。

无符号类型的表达式不能溢出,它们换行,例如, 0U - 1UINT_MAX

例子:

 INT_MAX + 1 // integer overflow UINT_MAX + 1 // no overflow, the resulting type is unsigned (unsigned char) INT_MAX // no overflow, integer conversion occurs 

永远不要让任何整数表达式过度,现代编译器(如gcc )利用整数溢出是未定义的行为来执行各种类型的优化。

例如:

 a - 10 < 20 

a在提升后为int类型时,表达式在gcc减少(启用优化时)到:

 a < 30 

aINT_MIN + 10 - 1INT_MIN范围内时,它利用表达式是未定义的行为。

aunsigned int时,无法完成此优化,因为如果a0 ,则a - 10必须被评估为UINT_MAX - 9 (没有未定义的行为)。 当a09时,优化a - 10 < 20a < 30将导致与所需结果不同的结果。

有符号整数的溢出是C中未定义的行为,因此无法保证。

也就是说,环绕或算术模2 N ,其中N是类型中的位数,是一种常见的行为。 对于那种行为,实际上如果一个和溢出,结果与操作数的符号相反。

forms上,有符号算术对溢出的行为是不确定的; 任何事情都可能发生,而且是’正确的’。 这与无符号算术形成对比,后者完全定义了溢出。

在实践中,许多较旧的编译器使用了在您描述时溢出的带符号算法。 然而,现代海湾合作委员会正在改变其运作方式,你依赖这种行为是非常不明智的。 当编译代码的环境中的任何内容发生变化时,它可能随时发生变化 – 编译器,平台……