7

如果我在 C 中执行以下代码:

#include <stdint.h>

uint16_t a = 4000;
uint16_t b = 8000;

int32_t c = a - b;

printf("%d", c);

结果它正确打印了“-4000”。但是,我有点困惑:从另一个减去一个更大的无符号整数时不应该有算术溢出吗?这里有什么铸造规则?这个问题似乎有点无聊,所以任何参考都将不胜感激。

4

4 回答 4

5

这个问题实际上有些复杂。算术表达式的操作数使用标准 (C89)的第 3.2.1.5 节中的特定规则进行转换。在您的情况下,答案取决于类型uint16_t是什么。如果它小于int,例如short int,那么操作数将被转换为int-4000,但在 16 位系统上,uint16_t可能是unsigned int并且不会自动转换为有符号类型。

于 2009-04-08T07:40:36.650 回答
3

简短的回答是,这些都是int在减法过程中提升的。对于长答案,请查看C 标准的第 6.3.1.1 节,其中讨论了算术表达式中的整数提升。标准中的相关语言:

如果 anint可以表示原始类型的所有值,则将该值转换为int; 否则,将其转换为unsigned int. 这些被称为整数促销。整数提升不会改变所有其他类型。

细节也在那里,但它们变得非常讨厌。

于 2009-04-08T07:35:55.633 回答
1

int32_t在减法期间,两个操作数都被提升。如果结果大于最大值,int32_t您会看到溢出。

于 2009-04-08T07:20:36.480 回答
0

事实上,有一个溢出,但 C 没有告诉你。

当解释为有符号整数时,溢出留下的值恰好是 -4000。这在 2 的补码机器上按设计工作。

尝试将结果解释为无符号,您会注意到 (u1-u2) 在 u1 < u2 时计算为一些看似无关的数字。

于 2009-04-08T07:56:02.167 回答