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"); } 

如果我们分成不同的部分:

  1. &x :这获取变量x所在位置的地址,即&x是指向x的指针。 类型是int *

  2. (char *)&x :这将获取(char *)&x的地址(这是一个int * )并将其转换为char *

  3. *(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))