分配给较大宽度的整数时的C整数溢出行为

时间:2009-04-08 07:14:35

标签: c casting integer overflow integer-overflow

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

#include <stdint.h>

uint16_t a = 4000;
uint16_t b = 8000;

int32_t c = a - b;

printf("%d", c);

结果正确打印'-4000'。但是,我有点困惑:当从另一个中减去一个更大的无符号整数时,不应该有算术溢出吗?这里有什么施法规则?这个问题看起来有些不自然,所以任何参考文献都会非常感激。

4 个答案:

答案 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)

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

当解释为有符号整数时,溢出会留下恰好为-4000的值。这是按照2的补充机器设计的。

尝试将结果解释为无符号,并且当u1&lt; u1时,您会注意到(u1-u2)评估为某些看似无关的数字。 U2。