所以当我输入以下命令
#include <stdio.h>
int main() {
int myInt;
myInt = 0xFFFFFFE2;
printf("%d\n",myInt);
return 0;
}
输出为-30
。
我想到了二进制补码,但是当我直接输入-30时,我也会得到相同的数字。所以我的问题是为什么我要以十六进制形式写我的数字?如果我使用十六进制格式,那么编译器如何区分0xFFFFFFE2是-30的二进制补码还是4294967266的值?
答案 0 :(得分:7)
这里存在一些误解,所有这些误解都可以通过回顾第一原理来解决:
数字就是数字。
当您写十进制文字42
时,即为数字42。
当您编写十六进制文字0x2A
时,仍然是数字42。
将这些表达式之一分配给int
时,int
包含数字42。
数字就是数字。
您使用的基础没关系。它什么都不会改变。以十六进制编写文字,然后将其分配给int
不会改变发生的情况。它不会神奇地使数字的解释,处理或表示具有任何不同。
数字就是数字。
您在这里完成的工作是将0xFFFFFFE2
(即4294967266)分配给myInt
。该数字大于平台上[signed] int
的最大值,因此它溢出。结果是不确定的,但您可能会看到“自动换行”为-30,这可能是由于补码表示形式是如何工作的以及如何在计算机的芯片和内存中实现的。
就是这样。
它与十六进制无关,因此在十六进制和十进制文字之间没有“选择”。如果使用十进制文字,也会发生相同的事情:
myInt = 4294967266;
此外,如果您正在寻找“触发”这种环绕行为的方法,请不要这样做,因为溢出具有不确定的行为。
如果您要操作构成myInt
的原始位和字节,可以通过char*
,unsigned char*
或std::byte*
对其进行别名处理方式。
答案 1 :(得分:1)
十六进制与十进制完全无关,为什么它不显示-30。
对于被视为带符号的32位单词(因为您使用的是%d),任何大于2147483648的无符号数字都将被视为负数(2s补码)
因此,myInt可能为-30、0xFFFFFFE2、4294967266或-0x1E,并将其视为带符号的32位整数将显示为-30。