大端小端数据读取

前言

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

什么是大端小端

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

  • 6
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值