如果我在C中执行以下代码:
#include <stdint.h>
uint16_t a = 4000;
uint16_t b = 8000;
int32_t c = a - b;
printf("%d", c);
结果正确打印'-4000'。但是,我有点困惑:当从另一个中减去一个更大的无符号整数时,不应该有算术溢出吗?这里有什么施法规则?这个问题看起来有些不自然,所以任何参考文献都会非常感激。
答案 0 :(得分:5)
这个问题实际上有些复杂。算术表达式的操作数使用特定规则进行转换,您可以在Standard (C89)的第3.2.1.5节中看到这些规则。在您的情况下,答案取决于类型uint16_t
是什么。如果它小于int
,比如short int
,那么操作数将转换为int
,你得到-4000,但在16位系统上,uint16_t
可能是unsigned int
并且转换为签名类型不会自动发生。
答案 1 :(得分:3)
简短的回答是,在减法期间,这些都被提升为int
。对于长期答案,请查看C standard的第6.3.1.1节,其中讨论了算术表达式中的整数提升。标准中的相关语言:
如果
int
可以代表所有值 原始类型,值是 转换为int
;否则就是 转换为unsigned int
。这些 被称为整数促销。 所有其他类型都没有改变 整数促销。
细节也在那里,但它们变得非常讨厌。
答案 2 :(得分:1)
在减法期间,两个操作数都被提升为int32_t
。如果结果大于int32_t
的最大值,您会看到溢出。
答案 3 :(得分:0)
当解释为有符号整数时,溢出会留下恰好为-4000的值。这是按照2的补充机器设计的。
尝试将结果解释为无符号,并且当u1&lt; u1时,您会注意到(u1-u2)评估为某些看似无关的数字。 U2。