intN_t 的溢出是否定义明确?

Is overflow of intN_t well-defined?

在 C99 中有一些(可选的)类型,如 int8_tint16_t 等,它们保证具有精确指定的宽度并且没有填充位,并且以二进制表示数字补充(7.18.1.1)。在 6.2.6.2 中,有符号整数溢出在脚注 44) 和 45) 中提到,即它可能导致在填充位 中捕获值

由于intN_t没有任何填充位,而且它们保证是二进制补码,这是否意味着它们的溢出不会产生任何未定义的行为?例如,结果会是什么?溢出乘法?加法呢?对于无符号类型,结果是否以 2^N 为模减少?

脚注不规范。如果脚注指出溢出会导致在填充位中捕获值,那并没有错,但我可以看出它有点误导。规范文本只是说行为是未定义的。在填充位中放置陷阱值是未定义行为的一种可能结果,但不是唯一的结果。

所以不,这并不意味着定义了溢出。涉及 intN_t/uintN_t 操作数的操作可能会溢出,并且该溢出会导致未定义的行为。

类似int8_t i = 127; ++i;的东西没有UB。 int8_t是积分提升的,所以加法是按照你写的i = (int8_t) ((int) i + 1);来进行的。添加本身不会溢出,转换回 int8_t 会产生一个实现定义的结果。

uint16_t u = 65535; u *= u; 这样的东西在当前典型的实现中有 UB,其中 int 有 32 sign/value 位。 uint16_t 也受整数提升的影响,所以乘法的执行就好像你写了 u = (uint16_t) ((int) u * (int) u); 一样。乘法本身溢出,行为未定义。

类似 int64_t i = 9223372036854775807; ++i; 的内容在几乎所有实现中都有 UB。添加本身溢出。

不,它没有明确定义,因为......它根本没有定义。标准中根本没有文本可以为有符号整数的溢出提供语义。

不要过分强调 "undefined behavior" 这个词是神秘的,但要理解它的直接含义。没有行为的定义,因此标准没有指定任何应该发生的事情,并且任何可移植代码都不应该依赖这样的特性。