大小端模式

来源:互联网 发布:三体 死神永生 知乎 编辑:程序博客网 时间:2024/06/04 18:34
19.大小端模式
大端模式(big endian)和小端模式(little endian)。
在我们发送数据的时候,我们首先要确定是大端还是小端模式来进行的,在接收方接收的数据必须知道数据是大端还是小端模式,才能正确地读取和存储数据起来,否则就会出错。
一个32位的二进制在内存中的存储时有2中分布方式:高字节对应高字节(大端模式)、高字节对应低地址(小端模式)。
有些时候CPU公司用大端(C51单片机);有些CPU用小端(ARM)。我们写代码的时候需要通过写代码来测试当前系统是打断还是小端模式。


方法1:用union来测试机器的大小端模式:共用体中很重要的一点:a和b都是从共用体的低地址开始的,我们在共用体的int变量中写入1,通过读取该共用体的char类型变量,如果该char值为1,说明数据是低地址对应低字节(小端),如果该char值是0,则说明是从低地址对应高字节(大端)。


union myunion
{
int a;
char b;
};
/*
共用体中很重要的一点:a和b都是从u1的低地址开始的,假设u1所在的4字节地址分别是:0/1/2/3的话,那么a自然就是0/1/2/3;那么char b所在的地址就是0而不是3;
所以当a = 1时,那么如果存储时是:0001,那么b = 1,则低字节存在低地址,小端模式
如果存储时是:1000,那么b= 0,则高字节对应低地址,大端模式。
*/
int is_little_endian1(void)
{
union myunion u1;
u1.a = 1;
return u1.b;
}


int main(void)


{
int i = is_little_endian1();
if(i)
{
printf("litte.\n");
}
else
{
printf("big.\n");
}
}


方法2:用指针方式来测试机器的大小端:其实本质上和union没有差多少,就是定义一个int a = 1;然后定义一个char b来指向a的首地址,然后通过b的值来判断是大端还是小端模式;如果b=1,说明a的存储方式是0001,即低字节存在低地址(小端);如果b=0,说明a的存储方式是1000,即高字节存在低地址(大端)。
解析:*(char *)(&a);首先对a取地址,将改地址强制转换为(char *)的类型,然后再解引用得出改地址中的内容。
int is_little_endian2(void)
{
int a = 1;
char b = *(char *)(&a);
return b;
}


看似可行实际不行的方法:
1.位与运算:位与运算时编译器提供的运算,这个运算是高于内存层次的,因为在进行位与运算的时候,一定是高字节 & 高字节的,所以无法判断出到底是大端还是小端模式。
2.移位:与位与运算一样,右移运算永远是将低字节移除,而和二进制存储时这个低字节在高位还是低位是无关的。
3.强制类型转换:与1、2同理。


20.通信系统中的大小端(数组的大小端):比如要通过串口发送一个0x12345678给接收方,但是因为串口本身限制,只能以字节为单位来发送,所以需要发4次;接收方分4次接受,内容分别是0x12,0x34,0x56,0x78.接收方接受到这4个字节之后需要去重组得到0x12345678。所以在通信双方需要有一个协议,就是要先发、先接高位还是低位?这就是通信中的大端、小端问题。
一般来说:先发低字节叫小端,先发高字节就叫大端。
0 0
原创粉丝点击