大端小端及其转换

计算机在存储数据的时候,是以字节(byte)为基本单位来存储的,因此存储单字节类型的数据(比如char)不存在字节序的问题。但存储多字节的数据的时候(比方说4字节的int变量),就涉及到了以一个什么样的顺序来存储。下面举例来说明大端和小端的存储方式。

定义变量 unsigned long long a=0x1122334455667788 

变量a是一个64位的无符号整数,共需要8个字节来存储,那么在两种模式下是如何存储的呢?

||--1--||--2--||--3--||--4--||--5--||--6--||--7--||--8--||  地址

||  11 ||  22 ||  33 ||  44 ||  55 ||  66 ||  77 ||  88 ||  大端模式
||  88 ||  77 ||  66 ||  55 ||  44 ||  33 ||  22 ||  11 ||  小端模式
从中很容易可以看出各自的存储特点。
大端:高地址存低字节,低地址存高字节
小端:低地址存低字节,高地址存高字节
小端模式:强制类型转换数据不需要调整字节内容。
大端模式:符号位判断固定为第一个字节,容易判断正负,便于人类阅读。

判断大小端

#include <QCoreApplication>
#include <QDebug>

bool isLittleEndian(){
    unsigned short a = 0x1218;

    if( (*(char*)&a)  == 0x18){
        return true;
    }else{
        return false;
    }
}


int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    if(isLittleEndian()){
        qDebug() << "LitteEndian";
    }else{
        qDebug() << "BigEndian";
    }

    return a.exec();
}

大小端转换

typedef unsigned short int uint16;
typedef unsigned long int uint32;
 
 
#define BigLittleSwap16(A)        ((((uint16)(A) & 0xff00) >> 8) | \
                                                       (((uint16)(A) & 0x00ff) << 8))
 
 
#define BigLittleSwap32(A)        ((((uint32)(A) & 0xff000000) >> 24) | \
                                                       (((uint32)(A) & 0x00ff0000) >> 8) | \
                                                       (((uint32)(A) & 0x0000ff00) << 8) | \
                                                       (((uint32)(A) & 0x000000ff) << 24))

Qt中大端小端的转换

Qt中<QtEndian>包含了大端小端转换的几个函数

T    qFromBigEndian(const uchar * src)
T    qFromBigEndian(T src)
T    qFromLittleEndian(const uchar * src)
T    qFromLittleEndian(T src)
void    qToBigEndian(T src, uchar * dest)
T    qToBigEndian(T src)
void    qToLittleEndian(T src, uchar * dest)
T    qToLittleEndian(T src)


下面对这个几个函数进行简单的说明。
   

 union{
        int a;
        char b[4];
    }test1,test2;
    test1.a=0x61626364;
    test2.a=qFromBigEndian(test1.a);
    qDebug()<<test1.b[0]<<test1.b[1]<<test1.b[2]<<test1.b[3];
    qDebug()<<test2.b[0]<<test2.b[1]<<test2.b[2]<<test2.b[3];


对于qFromBigEndian()函数,它会判断执行程序的主机的字节序,如果是大端模式的计算机,那么只是读取数据,不进行转换,如果是小端模式的计算机,那么则进行转换。
因此我在本机(小端模式)上的的执行结果是:

d c b a

a b c d

可以看出,它将数据进行了转换。
对于qFromLittleEndian()函数,和前者类似。对于大端模式的计算机进行转换,对于小端模式的计算机只是读取数据。

   

 union{
        int a;
        char b[4];
    }test1,test2;
    test1.a=0x61626364;
    test2.a=qFromLittleEndian(test1.a);
    qToBigEndian(test1.a,(uchar*)test2.b);
    qDebug()<<test1.b[0]<<test1.b[1]<<test1.b[2]<<test1.b[3];
    qDebug()<<test2.b[0]<<test2.b[1]<<test2.b[2]<<test2.b[3];


对于qToBigEndian()函数,也有着上面的规则,对于小端模式的计算机进行转换,对于大端模式的计算机只进行读取。
因此,本机(小端模式)的执行结果是:

d c b a

a b c d

对于qToLittleEndian()函数,只对大端模式的计算机进行转换。

需要注意的是,Qt中的模板T只针对有符号和无符号的整型,对于浮点型(一般也不会用到),需要进行强制类型转换。
 

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值