Little vs Big Endianess:如何解释测试

时间:2012-04-02 05:39:35

标签: c endianness

所以我正在编写一个程序来测试机器的endianess并打印它。 我理解小端和大端的区别,但是,从我在网上找到的,我不明白为什么这些测试显示机器的结束。

这是我在网上找到的。 *(char *)& x是什么意思,它如何证明机器是Little-Endian?

int x = 1;
if (*(char *)&x == 1) {
    printf("Little-Endian\n");
} else {
    printf("Big-Endian\n");
}

6 个答案:

答案 0 :(得分:14)

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

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

  2. (char *)&x:这会使用x的地址(int *)并将其转换为char *

  3. *(char *)&x:取消引用char *指向的&x,即获取x中存储的值。

  4. 现在我们回到x以及如何存储数据。在大多数机器上,x是四个字节。在1中存储x会将最低有效位设置为1,其余位设置为0。在小端机器上,它作为0x01 0x00 0x00 0x00存储在内存中,而在大端机器上,它存储为0x00 0x00 0x00 0x01

    表达式的作用是获取这些字节中的第一个并检查它是否为1

答案 1 :(得分:4)

这是内存的样子,假设一个32b整数:

Little-endian
0x01000000 = 00000001000...00

Big-endian
0x00000001 = 0......01

取消引用char *会给你一个字节。您的测试通过将地址解释为char * 然后取消引用它来获取该内存位置的第一个字节。

答案 2 :(得分:1)

分解*(char *)&x

&x是整数x的地址

(char *)导致整数x的地址被视为字符的地址(又称字节)

*引用字节的值

答案 3 :(得分:1)

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,则它是大端。

答案 4 :(得分:0)

是的,这回答了这个问题。这是一个更一般的答案:

#include <iostream>
#include <cstdlib>  
#include <cmath>

using namespace std;

int main()
{
cout<<"sizeof(char) = "<<sizeof(char)<<endl;
cout<<"sizeof(unsigned int) = "<<sizeof(unsigned int)<<endl;
//NOTE: Windows, Mac OS, and Linux and Tru64 Unix are Little Endian architectures
//Little Endian means the memory value increases as the digit significance increases
//Proof for Windows: 

unsigned int x = 0x01020408; //each hexadecimal digit is 4 bits, meaning there are 2
                             //digits for every byte
char *c = (char *)&x;
unsigned int y = *c*pow(16,0) +pow(16,2) * *(c+1)+pow(16,4) * *(c+2)+pow(16,6) * *(c+3);
//Here's the test: construct the sum y such that we select subsequent bytes of 0x01020408
//in increasing order and then we multiply each by its corresponding significance in
//increasing order.  The convention for hexadecimal number definitions is that  
//the least significant digit is at the right of the number.  
//Finally, if (y==x),then...     
if (y==x) cout<<"Little Endian"<<endl;
else cout<<"Big Endian"<<endl;

cout<<(int) *c<<endl;
cout<<(int) *(c+1)<<endl;
cout<<(int) *(c+2)<<endl;
cout<<(int) *(c+3)<<endl;
cout<<"x is "<<x<<endl;
cout<<(int)*c<<"*1 + "<<(int)*(c+1)<<"*16^2 + "<<(int)*(c+2)<<"*16^4 + "<<(int)*(c+3)<<" *16^6 = "<<y<<endl;
system("PAUSE"); //Only include this on a counsel program
return 0;
}

显示 8 4 2 1 对于c,c + 1,c + 2和c + 3处的解除引用值。 和y是16909320,等于x。即使数字的重要性从右向左增长,这仍然是Little Endian,因为相应的存储器值也从右向左增长,这就是左移二元运算符&lt;&lt;会增加变量的值,直到非零数字完全偏离变量。不要将此运算符与std :: cout的&lt;&lt;混淆运营商。 如果这是Big Endian,则c,c + 1,c + 2和c + 3的显示分别如下所示: 1 2 4 8

答案 5 :(得分:0)

如果big-endian 4字节无符号整数看起来像0xAABBCCDD等于2864434397,那么同样的4字节无符号整数在小端处理器上看起来像0xDDCCBBAA,也等于2864434397。

如果big-endian 2字节无符号短路看起来像0xAABB等于43707,那么相同的2字节无符号短路看起来像小端处理器上的0xBBAA,也等于43707。

以下是一些方便的#define函数,用于将字节从little-endian交换为big-endian,反之亦然 - &gt;

// 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))