为什么我能用十六进制表示大于MAXINT的int,而不是十进制?

时间:2017-08-24 15:39:34

标签: c int hex decimal

据我所知,十进制和十六进制只是(假设)int的表示。

这意味着如果我定义一个整数x,我应该能够将x打印为:

  • 小数:printf("%d", x);
  • 十六进制:printf("%x", x);

x超过MAXINT时,我不明白这是怎么回事。

以下面的代码为例:

#include<stdio.h>

int main(int argc, char** argv) {

    // Define two numbers that are both less than MAXINT
    int a =  808548400;
    int b = 2016424312;

    int theSum = a + b; // 2824972712 -> larger than MAXINT

    printf("%d\n", theSum); // -1469994584 -> Overflowed
    printf("%x\n", theSum); // A861A9A8 -> Correct representation

}

正如我的评论所示,这两个十进制数的总和是一个大于MAXINT的数字。这个数字在以小数形式打印时溢出(如我所料),但是当以十六进制打印时,它看起来非常好。

有趣的是,如果我继续添加此数字并导致它再次溢出,它将返回正确表示十进制数。十六进制数始终是正确的。

任何人都可以解释为什么会这样。

TIA

1 个答案:

答案 0 :(得分:3)

引用n1570(最新的C11草案),§7.21.6.1p8

  

[...]
   o,u,x,X unsigned int参数转换为无符号八进制( o ),无符号   十进制( u )或无符号十六进制表示法( x X )[...]

因此,简而言之,您在这里使用错误类型的转换说明符。实际上,您签名的溢出是未定义的行为,但您的实现显然使用2的补码来表示负数,并且溢出会导致系统上出现环绕,因此结果恰好是与正确的无符号号码相同的表示形式。

如果您使用%u代替%x,则会看到十进制表示法中的相同数字。同样,这将是未定义行为的结果,发生在您的系统上“正确”。始终避免签名溢出,结果允许任何