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

标签 c language-lawyer integer-promotion

编辑:更改了 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;

关于无符号整数加法可以调用未定义的行为吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37487730/

相关文章:

c++ - 标准布局和尾部填充

c++ - 为什么禁止在后续的私有(private)派生类中简单提及基指针/引用?

c - 在 printf 需要 int 的地方给 printf 一个 char 参数是 UB 吗?

integer-promotion - C 函数调用中的参数提升

c - 什么时候担心字节顺序?

c - Atmel Studio 7 不显示任何调试工具

c++ - C++ 中用户定义的文字命名

c++ - 为什么C/C++会自动将char/wchar_t/short/bool/enum类型转换为int?

多次复制字符串

c - 错误 : Bad address when using sendto() in raw sockets