首页 > 解决方案 > 在 C 中打印整数的实际位表示

问题描述

我想在 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");

对于第二种方法,输出是0000000202000000。我还尝试了其他数字,似乎字节在两者中交换了。哪一个是正确的?

标签: c

解决方案


欢迎来到异国情调的字节序世界。

因为我们先写数字的最高有效位,您可能会想象最高有效字节存储在较低地址。

制造计算机的电气工程师更有想象力。

有时他们首先存储最重要的字节,但在您的平台上它是最不重要的。

甚至有些平台有些混乱——但在实践中你很少会遇到这些。

所以我们大部分时间都在谈论大端和小端。这是一个关于格列佛游记的笑话,其中有一场关于煮鸡蛋从哪一端开始的毫无意义的战争。这本身就是对基督教会一些争论的讽刺。但我离题了。

因为您的第一个片段将值视为它遇到的一系列字节,然后按字节序排列。

但是因为它>>被定义为对位进行操作,所以它被实现为“逻辑地”工作,而不考虑实现。

C 不定义字节顺序是正确的,因为不支持 C 选择的模型的硬件将背负无休止且毫无意义地移动字节的开销。

遗憾的是,没有内置标识符告诉您模型是什么——尽管可以找到确实的代码。

如果(a)如上所述,您希望将整数类型分解为字节并对其进行操作,或者(b)您接收包含多字节结构的其他平台的文件,那么它将与您相关。

Unicode 在 UTF-16 和 UTF-32 中提供了一种称为 BOM(字节顺序标记)的东西。事实上,使用 UTF-8 的一个很好的理由(其中很多)是问题消失了。因为每个组件都是一个字节。

脚注: 在评论中已经相当公平地指出我没有讲述整个故事。C 语言规范允许整数的一种以上表示,特别是有符号整数。具体来说,有符号幅度、二进制补码和二进制补码。

它还允许不代表值的一部分的“填充位”。

因此,原则上,除了解决字节序问题,我们还需要考虑表示。

原则上。所有现代计算机都使用二进制补码,而使用其他任何东西的现存机器非常罕见,除非您真正需要支持此类平台,否则我建议您假设您使用的是二进制补码系统。


推荐阅读