在C99中有一些(可选)类型,如int8_t
,int16_t
等,它们保证具有精确指定的宽度和无填充位,并表示二进制补码中的数字( 7.18.1.1)。在6.2.6.2中,有符号整数溢出被提及为脚注44)和45),即它可能导致在填充位中捕获值 。
由于intN_t
没有任何填充位,并且它们保证是两个补码,这是否意味着它们的溢出不会产生任何未定义的行为?例如,结果会是什么?溢出乘法?添加怎么样?对于无符号类型,结果是否以模2^N
为模?
答案 0 :(得分:7)
脚注不是规范性的。如果一个脚注声明溢出会导致在填充位中捕获值,那么这并不是真的错误,但我可以看出它有多么误导。规范性文本仅表示行为未定义。将陷印值放在填充位中是未定义行为的一种可能结果,但不是唯一的结果。
所以不,这并不意味着定义溢出。涉及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个符号/值位。 uint16_t
也需要进行整体促销,因此乘法就像你写了u = (uint16_t) ((int) u * (int) u);
一样。乘法本身溢出,行为未定义。
像int64_t i = 9223372036854775807; ++i;
这样的东西几乎在所有实现上都有UB。添加本身就会溢出。
答案 1 :(得分:1)
不,它没有明确定义,因为......它根本没有定义。标准中没有任何文本可以为有符号整数的溢出提供语义。
不要过度强调术语“未定义的行为”是一种神秘的东西,但要直接理解它。没有行为的定义,因此标准没有指定应该发生什么,也没有可移植代码应该依赖于这样的功能。