大小端转换(一篇文章了解所有情况下的大小端转换方法)

您所在的位置:网站首页 字节和比特的换算方法 大小端转换(一篇文章了解所有情况下的大小端转换方法)

大小端转换(一篇文章了解所有情况下的大小端转换方法)

2024-07-05 03:38| 来源: 网络整理| 查看: 265

总述:

字节间字节内大端低地址的数据放在高字节位域:先从低地址对应数据字节的高bit开始分配小端低地址的数据放在低字节位域:先从低地址对应数据字节的低bit开始分配

注释: 对于大小端的几个结论: 1.char型变量和char型数组没有大小端的区分。 2.需要转化数据类型大于1个字节的数据类型:short,int,枚举,联合体等。 一.为什么要进行大小端转化? 简单说一下为什么要进行大小端转化:目前我接触到的,arm是小端,dsp是大端,电脑是小段,网络数据一般为大端,当arm需要和dsp通信的时候就会存在大小端转化的问题,每种芯片为什么选用大小端的由来就不赘述了。 二、字节间的大小端转化: 1,举例说明字节间的大小端: 内存中有如下一段数据(unsigned int 型),不同的大小端对这个段数据的理解不同,所以在我们实际工作中,当你查看到内存中的数据时候,首先要清楚这个处理器的大小端,才能理解这段数实际代表的值。

内存地址0x000040000x000040010x000040020x000040030X120x340x560X78如果是大端处理器:这段数代表:0x12345678;如果是小段处理器:这段数代表:0x78563412 ; 内存中有如下一段数据(unsigned short 型): 内存地址0x000040000x000040010X120x34

如果是大端处理器:这段数代表的值:0x1234; 如果是小段处理器:这段数代表的值:0x3412 ; 在两个不同大小端的处理器之间数据传输,数据再内存的存放顺序并没有变,不同大小端需要解读出通用的值,就需要进行大小端转化。 2,C语言大小端转化调用库函数:

htonlhost to network ,l代表unsigned long型 也可以看成unsigned inthtonshost to network ,s代表unsigned short型ntohlnetwork to host ,l代表unsigned long型 也可以看成unsigned intntohsnetwork to host ,s代表unsigned short型在网络传输中,一般要求是大端,而inter处理器是小端,network to host理解为大端转小端,而host to network 理解为小端转大端,本质上大端小端的转化算法是一致的,没有区别,3.代码验证: /* *程序说明:大小端字节间转化的一个案例 *作者 :通信小卒 *时间 :2019.8.25 */ #include #include #pragma comment(lib,"ws2_32.lib") int main(void) { unsigned int ultest=0x12345678; unsigned short ustest=0x1234; printf("ultest小端:%x\n",ultest); printf("ustest小端:%x\n",ustest); ultest=htonl(ultest);/*unsigned int 大小端转化*/ ustest=htons(ustest);/*unsigned short 大小端转化*/ printf("ultest大端:%x\n",ultest); printf("ustest大端:%x\n",ustest); while(1); }

在这里插入图片描述 三.对于字节内部位域大小端的理解与处理: 1.位域处理方法(特别注意): 大小端不同的芯片传递同一个结构体时, 第一步:需要将结构体中的位域部分根据大小端判断进行翻转(int型按照凑32bits翻转,short型凑16bits翻转 ,char型凑8bits翻转)。 第二步:接收到数据后,如果位域的数据类型是unsigned int型,就拼凑成32bits按照unsigned int进行大小端转化,如果是unsigned short 型就拼凑16bit按照unsigned short 进行大小端转化,如果是unsigned char型就不翻转。 2.案例说明位域的存储方式:

/* *程序说明:位域大小端字节转化的一个案例 *作者 :通信小卒 *时间 :2019.8.25 */ #include #include #define LOCAL_ENDIAN 1 /* 0为大端 1 为小端,根据处理器的类型赋值*/ typedef struct struct_test { #if LOCAL_ENDIAN unsigned int ula :7; unsigned int ulb :2; unsigned int ulc :5; unsigned int uld :3; unsigned int ule :6; unsigned int ulf :4; unsigned int ulg :5; #else unsigned int ulg :5; unsigned int ulf :4; unsigned int ule :6; unsigned int uld :3; unsigned int ulc :5; unsigned int ulb :2; unsigned int ula :7; #endif }struct_test_bit; int main(void) { struct_test_bit struct_test_endian; memset(&struct_test_endian,0,sizeof(struct_test_bit)); struct_test_endian.ula=0x57; struct_test_endian.ulb=0x3; struct_test_endian.ulc=0x1c; struct_test_endian.uld=0x6; struct_test_endian.ule=0x2d; struct_test_endian.ulf=0x9; struct_test_endian.ulg=0x1c; printf("&struct_test_endian=%x\n",&struct_test_endian); while(1); }

处理LOCAL_ENDIAN 不同,其他代码完全相同,在大小端不同的处理器上运行此代码,分析内存情况:

2.1在小端处理器下看内存(#define LOCAL_ENDIAN 1 ):

地址0X004AFC140X004AFC150X004AFC160X004AFC17数据十六进制D7B9DBE4数据二进制11010111101110011101101111100100跨字节的部分需要特别注意:在这里插入图片描述小端数据为:0x E4BDB9D7, 现将数据进行翻转看,然后从底地址数据开始读:在这里插入图片描述

可以看出小端是从底地址的字节的底bit位开始分配。 2.2在大端处理器运行看内存(#define LOCAL_ENDIAN 0):

地址0X004AFC140X004AFC150X004AFC160X004AFC17数据十六进制E4DBB9D7数据二进制11100100110110111011100111010111跨字节的部分需要特别注意:在这里插入图片描述三.对于枚举类型与联合体类型的处理。1.对于枚举类型按照unsigned int进行大小端转化就可以。2.对于联合体按照联合体中长度最长的数据类型以及长度进行转化就行。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3