无符号整数加法可以调用未定义的行为吗?
Can an unsigned integer addition invoke undefined behavior?
编辑: 更改了 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;
Can an unsigned integer addition invoke undefined behaviour?
这取决于。
如果
int
的秩大于所讨论的两个操作数(此处为 unsigned short int
,因此在这种情况下为真) 和
- 有问题的两个操作数的值将适合
int
(重要 corner case if not*1 ) 和
- 算术运算(这里是加法)会溢出
那么是的,这将调用 UB。
原因:
- 有问题的操作数(此处为
unsigned short int
s)在算术运算中被提升为 int
(在 *1 的情况下则不会) .
int
上的溢出算术运算调用 UB。
*1:
如果操作数确实 not 适合 int
它被提升为 unsigned int
并且根据这个任何算术运算2. 以上将不会调用UB。
编辑: 更改了 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;
Can an unsigned integer addition invoke undefined behaviour?
这取决于。
如果
int
的秩大于所讨论的两个操作数(此处为unsigned short int
,因此在这种情况下为真) 和- 有问题的两个操作数的值将适合
int
(重要 corner case if not*1 ) 和 - 算术运算(这里是加法)会溢出
那么是的,这将调用 UB。
原因:
- 有问题的操作数(此处为
unsigned short int
s)在算术运算中被提升为int
(在 *1 的情况下则不会) . int
上的溢出算术运算调用 UB。
*1:
如果操作数确实 not 适合 int
它被提升为 unsigned int
并且根据这个任何算术运算2. 以上将不会调用UB。