联合中的字符字节是否反转?
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
无论您的字节顺序如何,移位结果都适用于此表示形式,因此移位不是检测字节顺序的好方法。您的机器可能是小端(由于这些结果和基本速率,因为大多数计算机都是小端)。
我有一个包含 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
无论您的字节顺序如何,移位结果都适用于此表示形式,因此移位不是检测字节顺序的好方法。您的机器可能是小端(由于这些结果和基本速率,因为大多数计算机都是小端)。