理解 C 中的整数和

Understanding integer sum in C

我试图从标准的正式角度正式理解加法运算符的工作原理。有 2 个项目符号:

4 If both operands have arithmetic type, the usual arithmetic conversions are performed on them.

5 The result of the binary + operator is the sum of the operands.

考虑以下代码

unsigned int m = UINT_MAX;
printf("%d\n", m + 1);

我们有 UINT_MAX + 1 不适合 unsigned int 的宽度,因此表示结果 unsigned int 是不够的。所以我找到了描述无符号整数转换的部分:

if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.

这里的新类型是unsigned int,但是问题是那么旧类型是什么?它不能是 unsigned int,因为 unsigned int 的宽度太小,无法表示结果值。

旧类型分别为unsigned intintUINT_MAX1

引用的文字描述了数学结果,数学不限于C类型。

It cannot be unsigned int since the resulting value cannot be represented due to the width of unsigned int is too small.

该说法不正确。

(以下引用自标准草案 N1570。)

代码正在添加一个 unsigned int 和一个 signed int

第 6.3.1.8 节通常的算术转换描述了发生的情况。相关部分是:

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

6.3.1.1布尔、字符和整数告诉我们

The rank of any unsigned integer type shall equal the rank of the corresponding signed integer type, if any.

所以这两部分告诉我们,在 unsigned-int + signed-int 的情况下,signed int 将被转换为 unsigned int。因此,在您的具体示例中,“旧类型”确实是 unsigned int.

关于运算结果第6.2.5节类型告诉我们:

A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.

换句话说,您的代码的结果为零,类型为 unsigned int

所以相关的转换在6.3.1.3有符号和无符号整数

When a value with integer type is converted to another integer type other than _Bool, if the value can be represented by the new type, it is unchanged.