大端小端数据读取

来源:互联网 发布:cn域名好不好 编辑:程序博客网 时间:2024/06/12 21:43

前言

前段时间在做二进制数据读取时候,发现读取的数据总是有问题。错误原因就是涉及到大端小端数据读取方式的问题,下面就是将这部分内容做一总结。

什么是大端小端

大小端模式就是存储数据时,数据的高低位是怎么存储在地址的高低位上。
大端模式(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

0 0