我试图从标准的形式角度正式理解加法运算符是如何工作的。有2个项目:
4如果两个操作数都是算术类型,则通常的算术类型对它们执行转换。
5二进制+的结果操作符是操作数的和。
考虑下面的代码
unsigned int m = UINT_MAX;
printf("%dn", m + 1);
我们知道UINT_MAX + 1
不适合unsigned int
的宽度,所以unsigned int
不足以表示结果。所以我找到了一个描述无符号整数转换的章节:
如果新类型是无符号的,则值被反复转换加上或减去比最大值多一个的值在new类型的范围内之前,用新类型表示类型。
这里的新类型是unsigned int
,但问题是什么是旧类型,然后? 它不能是unsigned int
,因为unsigned int
的宽度太小,结果值无法表示。
不能为unsigned int,因为unsigned int的宽度太小,结果值无法表示。
这个说法是不正确的。
(以下引语来自标准草案N1570)
代码正在添加一个unsigned int
和一个signed int
。
第6.3.1.8节描述了通常的算术转换。相关部分为:
否则,如果为无符号整数类型的操作数的排名大于或等于rank另一个操作数的类型,然后操作数with带符号整数类型转换为带unsigned的操作数类型整数类型。
和6.3.1.1布尔值、字符和整数告诉我们
任何无符号整型的秩等于秩对应的有符号整数类型,如果有的话。
所以这两个部分告诉我们,在unsigned-int + signed-int
的情况下,有符号整型将被转换为无符号整型。在你的具体例子中,旧的类型;确实是unsigned int
.
对于第6.2.5节类型操作的结果告诉我们:
涉及无符号操作数的计算永远不会溢出,因为无法用所产生的无符号整数类型表示的结果是取比最大值大1的数的约模由结果类型表示。
换句话说,代码的结果是0,类型为unsigned int
。
相应的转换在6.3.1.3有符号整数和无符号整数
当将整型值转换为非_Bool类型的整型值时,如果该值可以用新的类型表示,它是不变的。
旧类型分别为unsigned int
和int
、UINT_MAX
和1
。
引用的措辞描述了数学结果,数学并不局限于C类型。