【发布时间】:2015-06-14 12:29:41
【问题描述】:
在 C99 中,有一些(可选)类型,如 int8_t、int16_t 等,它们保证具有精确指定的宽度且没有填充位,并以二进制补码表示数字 (7.18.1.1) .在 6.2.6.2 中,有符号整数溢出在脚注 44) 和 45) 中提到,即它可能导致在填充位中捕获值。
由于intN_t 没有任何填充位,并且它们保证是二进制补码,这是否意味着它们的溢出不会产生任何未定义的行为?例如,结果会是什么?溢出乘法?加法呢?结果是否与无符号类型一样以 2^N 为模减少?
【问题讨论】:
-
IANALL 但即使它们用 2 的补码表示,它们仍然不遵守算术模 2^n 的定律,因此溢出的结果在数学上没有定义。标准规定“如果在评估表达式期间,结果未在数学上定义或不在其类型的可表示值范围内,则行为未定义。”。
-
即使对于
uintN_t,溢出也不是(通常)明确定义的。intN_t和uintN_t仍然受到整数提升的影响,并且可以在uint16_t提升为int的系统上将两个uint16_t值相乘,以产生无法在 @987654331 中表示的结果@. -
注意:
int8_t、int16_t等类型在 C99 中并非完全可选:“这些类型是可选的。但是,如果实现提供宽度为 8、16、32 或64 位,无填充位,并且(对于有符号类型)具有二进制补码表示,它应定义相应的 typedef 名称。” §7.20.1.1 3 -
@hvd:我想知道在加法、乘法、按位或左移运算符的结果被强制转换或强制为更小的无符号类型的情况下,是否会有任何实际困难与
int相比,编译器必须生成代码,其行为就像运算符将其操作数强制转换为该类型并使用该类型执行操作一样,或者定义__STDC_NON_MODULAR_UNSIGNED_SHORT。请注意,几乎所有在 2010 年之前生产的编译器(以及之后生产的许多编译器)都已遵守该规则,并且大多数都可以遵守... -
...使用命令行选项。该规则不需要对标准定义的任何行为进行任何更改,并且不太可能与任何编译器扩展的任何已定义行为相矛盾。该规则的唯一效果是更改某些类型的未定义行为,这将导致有用优化为独立于平台的行为。
标签: c int undefined-behavior integer-overflow