Little vs Big Endianess:如何解释测试
所以我正在编写一个程序来测试机器的endianess并打印它。 我理解小端和大端的区别,但是,从我在网上找到的,我不明白为什么这些测试显示了机器的结束。
这就是我在网上找到的。 *(char *)&x是什么意思,它与一个机器是Little-Endian的相同之处是什么?
int x = 1; if (*(char *)&x == 1) { printf("Little-Endian\n"); } else { printf("Big-Endian\n"); }
如果我们分成不同的部分:
-
&x
:这获取变量x
所在位置的地址,即&x
是指向x
的指针。 类型是int *
。 -
(char *)&x
:这将获取(char *)&x
的地址(这是一个int *
)并将其转换为char *
。 -
*(char *)&x
:取消引用*(char *)&x
指向的char *
,即获取存储在x
的值。
现在,如果我们回到x
以及如何存储数据。 在大多数机器上, x
是四个字节。 在x
存储1
将最低有效位设置为1
,其余位设置为0
。 在小端机器上,它作为0x01 0x00 0x00 0x00
存储在内存中,而在大端机器上它存储为0x00 0x00 0x00 0x01
。
表达式的作用是获取这些字节中的第一个并检查它是否为1
。
假设一个32b整数,这就是内存的样子:
Little-endian 0x01000000 = 00000001000...00 Big-endian 0x00000001 = 0......01
取消引用char *
会给你一个字节。 您的测试通过将地址解释为char *
然后解除引用来获取该内存位置的第一个字节。
分解*(char *)&x
:
&x
是整数x的地址
(char *)
导致整数x的地址被视为字符的地址(又称字节)
*
引用字节的值
int x;
x
是一个可以保存32位值的变量。
int x = 1;
给定硬件可以将值1
存储为以下格式之一的32-bit
值。
Little Endian 0x100 0x101 0x102 0x103 00000001 00000000 00000000 00000000 (or) Big Endian 0x100 0x101 0x102 0x103 00000000 00000000 00000000 00000001
现在让我们尝试打破表达式:
&x
获取变量x
的地址。 假设x
的地址是0x100
。
(char *)&x
&x
是整数变量的地址。 (char *)&x
将地址0x100
从(int *)
为(char *)
。
*(char *)&x
取消引用存储在(char *)
的值,该值只是4字节(32位整数x
)中的第一个字节(从左到右)。
(*(char *)&x == 1)
如果从左到右的第一个字节存储值00000001
,则它是小端。 如果从左到右的第4个字节存储值00000001
,那么它是大端。
是的,这回答了这个问题。 这是一个更一般的答案:
#include #include #include using namespace std; int main() { cout<<"sizeof(char) = "<
对于c,c + 1,c + 2和c + 3处的解除引用值,这分别显示8 4 2 1。 和y是16909320,等于x。 尽管数字的重要性从右向左增长,但这仍然是Little Endian,因为相应的内存值也从右向左增长,这就是左移二元运算符<<会增加变量值的原因直到非零数字完全偏离变量。 不要将此运算符与std :: cout的<<运算符混淆。 如果这是Big Endian,则c,c + 1,c + 2和c + 3的显示分别为:1 2 4 8
如果big-endian 4字节无符号整数看起来像0xAABBCCDD等于2864434397,那么相同的4字节无符号整数在小端处理器上看起来像0xDDCCBBAA,它也等于2864434397。
如果一个大端2字节无符号短路看起来像0xAABB等于43707,那么相同的2字节无符号短路看起来像小端处理器上的0xBBAA,也等于43707。
这里有几个方便的#define函数可以将字节从little-endian交换到big-endian,反之亦然 – >
// can be used for short, unsigned short, word, unsigned word (2-byte types) #define BYTESWAP16(n) (((n&0xFF00)>>8)|((n&0x00FF)<<8)) // can be used for int or unsigned int or float (4-byte types) #define BYTESWAP32(n) ((BYTESWAP16((n&0xFFFF0000)>>16))|((BYTESWAP16(n&0x0000FFFF))<<16)) // can be used for unsigned long long or double (8-byte types) #define BYTESWAP64(n) ((BYTESWAP32((n&0xFFFFFFFF00000000)>>32))|((BYTESWAP32(n&0x00000000FFFFFFFF))<<32))