联合中的字符字节是否反转?

Are char bytes in unions reversed?

我有一个包含 int 和 char 的联合,如下所示:

union {
    int     i;
    char    c[4];
} num;

当我将 int 设置为 1 并打印每个字符时,我得到了这个结果:

1 0 0 0

...让我得出结论,我的机器是小端。 但是,当我向左移动 24 位时,我得到以下信息:

0 0 0 1

通过自定义函数交换字节顺序(通过交换最左边的字节和右边的字节,中间两个字节相同),我最终得到:

0 0 0 1

左移 24 结果:

0 0 0 0

这使我得出结论,联合中的 char[4] 是从右到左表示的,在这种情况下,字节序实际上与所表示的相反。但据我了解,char 数组通常是从左到右解释的,与平台无关。 我的 union 中的 char 字节是否颠倒了?

完整代码在这里:

#include <stdio.h>
#include <stdlib.h>

void    endian_switch32(int *n)
{
    int ret[4];

    ret[0] = *n >> 24;
    ret[1] = (*n >> 8) & (255 << 8);
    ret[2] = (*n << 8) & (255 << 16);
    ret[3] = *n << 24;
    *n = ret[0] | ret[1] | ret[2] | ret[3];
}

int main (void) {

    union {
        int     i;
        char    c[4];
    } num;

    num.i = 1;
    printf("%d %d %d %d\n", num.c[0], num.c[1], num.c[2], num.c[3]);

    num.i <<= 24;
    printf("%d %d %d %d\n", num.c[0], num.c[1], num.c[2], num.c[3]);

    num.i = 1;
    printf("%d %d %d %d\n", num.c[0], num.c[1], num.c[2], num.c[3]);

    endian_switch32(&num.i);
    printf("%d %d %d %d\n", num.c[0], num.c[1], num.c[2], num.c[3]);

    num.i <<= 24;
    printf("%d %d %d %d\n", num.c[0], num.c[1], num.c[2], num.c[3]);

}

结果:

1 0 0 0
0 0 0 1
1 0 0 0
0 0 0 1
0 0 0 0

重点是,您要以相反的顺序 打印字节 ,因此您要将 0x01020304 打印为 4 3 2 1,这导致你的困惑。 Endian 影响数组的存储方式,即没有人"reverse store"一个数组。

当你将 1 右移 24 时,你得到零。没关系:

 00000000 00000000 00000000  00000001
 ->
(00000000 00000000 00000000) 00000000 00000000 00000000 00000001
 ->
 00000000 00000000 00000000 00000000

正好为零。

当你将 0x01000000 右移 24 位时,你得到 1。结论(来自 char[4] 的打印输出)是你的平台是小端。

左移和右移基于 int 的值,而不是其二进制表示。无论字节如何存储在内存中,一个值为 1 的 32 位 int 在逻辑上被认为是 0x00000001,或二进制

00000000 00000000 00000000 00000001

无论您的字节顺序如何,移位结果都适用于此表示形式,因此移位不是检测字节顺序的好方法。您的机器可能是小端(由于这些结果和基本速率,因为大多数计算机都是小端)。