编辑:更改了 USHRT_MAX
的值,因为它不符合评论所示。
假设您有一个奇特的编译器,其整数类型限制(如 limits.h 中所定义)是:
#define INT_MAX 2147483647 /* Typical 32-bit system value */
#define USHRT_MAX 2147483647 /* ***Edited***, original question had 2000000000 */
在我的应用程序中,我有以下代码:
unsigned short a = 1500000000;
unsigned short b = 1500000000;
unsigned short c;
c = a + b;
据我所知,最后一条指令会发生什么:
a
积分促销。由于int
可以采用unsigned short
的所有值,因此a
被提升为int
。- 出于同样的原因,
b
被提升为int
。 - 加法发生在
int
类型上。 - 结果无法用
int
表示。由于第 6.5/5 段而导致的未定义行为。
我的推理正确吗?这真的会调用未定义的行为,还是我哪里出错了?请注意,我的代码仅适用于无符号类型,并且由于无符号类型的合法溢出,可能会出现对无符号整数应用模数的结果。
如果上一个问题的答案是“是的,未定义的行为”,这发生在合法的编译器上。那么,你能说我贴的应用代码不正确吗?是否所有非显式转换的小无符号整数加法都可能调用未定义的行为?
最佳答案
USHRT_MAX 不能定义为 2000000000。无符号整数的最大值必须是这样的形式:2^n-1:
6.2.6.2 Integer types
- For unsigned integer types other than unsigned char, the bits of the object representation shall be divided into two groups: value bits and padding bits (there need not be any of the latter). If there are N value bits, each bit shall represent a different power of 2 between 1 and 2 N−1 , so that objects of that type shall be capable of representing values from 0 to 2 N − 1 using a pure binary representation; this shall be known as the value representation. The values of any padding bits are unspecified.
假设 USHRT_MAX 是 2^31-1,INT_MAX 是 2^31-1。
在这种情况下,由于整数提升,变量 a
和 b
将被提升为类型 int
,并且签名的结果添加会溢出。
gcc 足够聪明,可以在将两个无符号短整型变量赋值给一个无符号短整型时将它们相加视为无符号。
然而,为了完全的可移植性,代码应该是:
c = a + 0u + b;
关于无符号整数加法可以调用未定义的行为吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37487730/