intN_t 的溢出是否定义明确?
Is overflow of intN_t well-defined?
在 C99 中有一些(可选的)类型,如 int8_t
、int16_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" 这个词是神秘的,但要理解它的直接含义。没有行为的定义,因此标准没有指定任何应该发生的事情,并且任何可移植代码都不应该依赖这样的特性。
在 C99 中有一些(可选的)类型,如 int8_t
、int16_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" 这个词是神秘的,但要理解它的直接含义。没有行为的定义,因此标准没有指定任何应该发生的事情,并且任何可移植代码都不应该依赖这样的特性。