整数溢出是 C 中未定义的行为。
C 说一个涉及整数的表达式溢出,如果它在通常的算术转换之后的结果是有符号类型的并且不能用结果的类型表示。赋值和强制转换表达式是一个例外,因为它们受整数转换的约束。
无符号类型的表达式不能溢出,它们会换行,例如0U - 1is UINT_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
Run Code Online (Sandbox Code Playgroud)
永远不要让任何整数表达式溢出,现代编译器(如gcc)利用整数溢出作为未定义行为来执行各种类型的优化。
例如:
a - 10 < 20
Run Code Online (Sandbox Code Playgroud)
whena是int提升后的类型,表达式在gcc(启用优化时)减少为:
a < 30
Run Code Online (Sandbox Code Playgroud)
当a在INT_MIN + 10 - 1to范围内时,它利用表达式是未定义的行为INT_MIN。
当ais时无法进行此优化,unsigned int因为如果a是0,则a - 10必须将其评估为UINT_MAX - 9(无未定义行为)。优化a - 10 < 20到a < 30那么将导致不同的结果,当需要的一个a是0到9。
形式上,有符号算术在溢出时的行为是未定义的;任何事情都可能发生,而且它是“正确的”。这与无符号算术形成对比,后者完全定义了溢出。
\n\n在实践中,许多较旧的编译器使用有符号算术,如您所描述的那样会溢出。然而,现代 GCC 正在改变它的工作方式,你依赖这种行为是非常不明智的。当编译代码的环境中的任何内容发生变化时,它可能随时发生变化 \xe2\x80\x94 编译器、平台......
\n