前言
前段时间在做二进制数据读取时候,发现读取的数据总是有问题。错误原因就是涉及到大端小端数据读取方式的问题,下面就是将这部分内容做一总结。
什么是大端小端
大小端模式就是存储数据时,数据的高低位是怎么存储在地址的高低位上。
大端模式(Most Significant Byte,MSB):数据的高位,存放在地址的低位,即高位存低位,低位存高位。
小端模式(Least Significant Byte,LSB):数据的高位,存放在地址的高位,即高位存高位,低位存低位。
明显小端模式更符合我们日常记录书写的习惯,pc机一般都是小端模式。
当我们使用的pc机和待读取数据大小端不一致时候,要特别注意,要使用相应的方式进行读取数据,具体方式看下文。
大端小端判断
方法1:
void main(){
short int x;
char x0,x1;
x=0x1122;
x0=((char *)&x)[0]; //低地址单元
x1=((char *)&x)[1]; //高地址单元
printf("x0=0x%x,x1=0x%x",x0,x1);// 若x0=0x11,则是大端; 若x0=0x22,则是小端......
uint32_t i=0x04030201;
unsigned char* cp=(unsigned char*)&i;
if(*cp==1)
printf("little-endian\n");
else if(*cp==4)
printf("big-endian\n");
else
printf("who knows?\n");
}
方法2,通过联合体判断:
#include<stdio.h>
union var{
char c[4];
int i;
};
int main(){
union var data;
data.c[0] = 0x04;//因为是char类型,数字不要太大,算算ascii的范围~
data.c[1] = 0x03;//写成16进制为了方便直接打印内存中的值对比
data.c[2] = 0x02;
data.c[3] = 0x11;
//数组中下标低的,地址也低,按地址从低到高,内存内容依次为:04,03,02,11。总共四字节!
//而把四个字节作为一个整体(不分类型,直接打印十六进制),应该从内存高地址到低地址看,0x11020304,低位04放在低地址上。
printf("%x\n",data.i);
}
大端数据读取
二进制数据的存储一般会伴随着一个数据说明文档,在文档中会有数据的存储方式,如:NASA提供的激光高度计数据(IMG后缀),其说明文档里有如下信息,说明该存储方式位大端:
LINES = 5632
LINE_SAMPLES = 11520
SAMPLE_TYPE = MSB_INTEGER
SAMPLE_BITS = 16
UNIT = METER
END_OBJECT = IMAGE
若我们的pc机是小端,在写codes读取数据时候要考虑将大端转小端。
大小端转换
定义宏:
typedef unsigned int uint_32 ;
typedef unsigned short uint_16 ;
大小端转换16位:
#define BSWAP_16(x) \
(uint_16)((((uint_16)(x) & 0x00ff) << 8) | \
(((uint_16)(x) & 0xff00) >> 8) \
)
大小端转换32位:
#define BSWAP_32(x) \
(uint_32)((((uint_32)(x) & 0xff000000) >> 24) | \
(((uint_32)(x) & 0x00ff0000) >> 8) | \
(((uint_32)(x) & 0x0000ff00) << 8) | \
(((uint_32)(x) & 0x000000ff) << 24) \
)
定义函数:
大小端转换16位:
uint_16 bswap_16(uint_16 x)
{
return (((uint_16)(x) & 0x00ff) << 8) | \
(((uint_16)(x) & 0xff00) >> 8) ;
}
大小端转换32位
uint_32 bswap_32(uint_32 x)
{
return (((uint_32)(x) & 0xff000000) >> 24) | \
(((uint_32)(x) & 0x00ff0000) >> 8) | \
(((uint_32)(x) & 0x0000ff00) << 8) | \
(((uint_32)(x) & 0x000000ff) << 24) ;
}
调用方式
sInt 是读取的短整型数据。
sInt = BSWAP_16(sInt);
sInt = bswap_16(sInt);
结语
其中代码可以直接用于大小端数据转换。
博客地址:http://blog.csdn.net/wokaowokaowokao12345/article/details/71534472
参考:
http://blog.csdn.net/xhhjin/article/details/7779716
http://blog.csdn.net/szchtx/article/details/42834391
http://blog.csdn.net/huqinwei987/article/details/23597091
http://www.xuebuyuan.com/2155119.html