无符号整数加法可以调用未定义的行为吗?

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;

据我所知,最后一条指令会发生什么:

  1. a 积分促销。由于 int 可以取 unsigned short 的所有值,a 被提升为 int
  2. 出于同样的原因,b 晋升为 int
  3. 添加发生在 int 类型上。
  4. 结果无法在 int 中表示。由于段落 6.5/5 导致的未定义行为。

我的推理是否正确?这真的会调用未定义的行为,还是我哪里出错了?请注意,我的代码仅适用于无符号类型,并且由于无符号类型的合法溢出,可以预期对无符号整数应用模数的结果。

如果上一个问题的答案是“是的,未定义的行为”,这发生在合法的编译器上。那么,你能说我贴的应用代码不正确吗?是否所有非显式转换的小无符号整数加法都可能调用未定义的行为?

不可能将USHRT_MAX定义为2000000000。无符号整数的最大值必须为:2^n-1:

6.2.6.2 Integer types

  1. 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。

在这种情况下,由于整数提升,变量 ab 将被提升为类型 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。

原因:

  1. 有问题的操作数(此处为 unsigned short ints)在算术运算中被提升为 int(在 *1 的情况下则不会) .
  2. int 上的溢出算术运算调用 UB。

*1: 如果操作数确实 not 适合 int 它被提升为 unsigned int 并且根据这个任何算术运算2. 以上将不会调用UB。