我想在 C 中打印整数的实际位表示。这是我发现的两种方法。
首先:
union int_char {
int val;
unsigned char c[sizeof(int)];
} data;
data.val = n1;
// printf("Integer: %p\nFirst char: %p\nLast char: %p\n", &data.f, &data.c[0], &data.c[sizeof(int)-1]);
for(int i = 0; i < sizeof(int); i++)
printf("%.2x", data.c[i]);
printf("\n");
第二:
for(int i = 0; i < 8*sizeof(int); i++) {
int j = 8 * sizeof(int) - 1 - i;
printf("%d", (val >> j) & 1);
}
printf("\n");
对于第二种方法,输出为 00000002
和 02000000
。我还尝试了其他数字,似乎字节在两者中交换了。哪一个是正确的?
最佳答案
欢迎来到充满异国情调的字节序世界。
因为我们首先写入数字的最高有效位,所以您可能会认为最高有效字节存储在较低地址。
制造计算机的电气工程师更有想象力。
有时他们首先存储最高有效字节,但在您的平台上它是最不重要的。
甚至有些平台有点困惑 - 但您在实践中很少遇到。
所以我们大部分时间都在谈论大端和小端。这是关于格列佛游记的一个笑话,其中有一场关于从煮鸡蛋的哪一端开始的毫无意义的 war 。这本身就是对基督教会中一些争论的讽刺。但我离题了。
因为您的第一个代码段将值视为它遇到的一系列字节,然后按字节顺序排列。
但是因为 >>>
被定义为对位进行操作,所以它被实现为“逻辑上”工作,而不考虑实现。
C 不定义字节顺序是正确的,因为不支持 C 选择的模型的硬件将承受无休止和毫无意义的改组字节的开销。
遗憾的是,没有内置标识符告诉您模型是什么 - 尽管可以找到可以找到的代码。
如果 (a) 如上所述,您希望将整数类型分解为字节并对其进行操作,或者 (b) 您收到包含多字节结构的其他平台的文件,这将与您相关。
Unicode 在 UTF-16 和 UTF-32 中提供了一种称为 BOM(字节顺序标记)的东西。 事实上,使用 UTF-8 的一个很好的理由(在许多理由中)就是问题消失了。因为每个组件都是一个字节。
脚注: 评论中已经相当公正地指出我没有讲完整个故事。 C 语言规范接受不止一种整数表示,特别是有符号整数。特别是符号大小、二进制补码和个数补码。
它还允许不代表值的一部分的“填充位”。
因此原则上,除了解决字节顺序问题,我们还需要考虑表示。
原则上。所有现代计算机都使用二进制补码,而使用其他任何东西的现存计算机非常罕见,除非您确实需要支持此类平台,否则我建议您假设您使用的是二进制补码系统。
关于c - 在 C 中打印整数的实际位表示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51517322/