据我所知,十进制和十六进制只是(假设)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
答案 0 :(得分:3)
引用n1570(最新的C11草案),§7.21.6.1p8:
[...]
o,u,x,Xunsigned int
参数转换为无符号八进制( o ),无符号 十进制( u )或无符号十六进制表示法( x 或 X )[...]
因此,简而言之,您在这里使用错误类型的转换说明符。实际上,您签名的溢出是未定义的行为,但您的实现显然使用2的补码来表示负数,并且溢出会导致系统上出现环绕,因此结果恰好是与正确的无符号号码相同的表示形式。
如果您使用%u
代替%x
,则会看到十进制表示法中的相同数字。同样,这将是未定义行为的结果,发生在您的系统上“正确”。始终避免签名溢出,结果允许任何。