文章目录
- 大小端
- 前言
- 函数引用(接下来使用此函数对高低位进行切换)
- 先看截取的对于大小端的定义
- 大小端数据的直观理解[重点]
- 对uchar数组进行取操作
- 定义一个uint8_t的数组观察起内部内存
- 尝试使用uint32_t 每次区 1、2、3、4byte数据
- 提升
- 经过上面的介绍一定对大小端有了一定的了解,那么接下来进行的是 memcpy数组到另一个数组
- uchar[]给uchar[]
- uint32_t[]给uint32_t[]
- uint32_t[]给uint8_t[]
- 本项目代码
- 结语
大小端
前言
在讨论大小端前我们先要了解: memset 和 memcpy 函数,它们的最小单位是以字节(byte)为单位。
函数引用(接下来使用此函数对高低位进行切换)
void MainWindow::reverseArray(char *src, char *dest, uint length)
{for(uint i=0; i<length/4; i++){dest[4*i+0] = src[4*i+3];dest[4*i+1] = src[4*i+2];dest[4*i+2] = src[4*i+1];dest[4*i+3] = src[4*i];}
}
先看截取的对于大小端的定义
大小端数据的直观理解[重点]
* 为什么要区分 大小端字节序* 如:0x12345678(此种写法 左侧高字节 右侧低字节)* 地址显示: 0000 0001 0002 0003* 小端显示: 78 56 34 12* 大端显示: 12 34 56 78* 我们知道当我们 memset或memcpy从内存读数时都是从低地址往出读的* 注意:我们读出来数据时是从低位读的,* 那么小端模式下(读出来的低地址数据在低位):读出来的数写到 目的地址的时候也是依次向右挤的(头插法)* 在大端模式下(读出来的低地址数据在高位):读出来的数写到 目的地址的时候是依次向右添加的(尾插法)* 此时当我们memset 1字节时读出来的是:* 小端读小端:0x 78* 大端读大端:0x 12* 小端机器上读大端数据0x 12* * 此时当我们memset 2字节时读出来的是:* 小端读小端:0x 56 78* 大端读大端:0x 12 34* 小端机器上读大端数据:0x 34 12* * 此时当我们memset 3字节时读出来的是:* 小端读小端:0x 34 56 78* 大端读大端:0x 12 34 56* 小端机器上读大端数据:0x 56 34 12* * 此时当我们memset 4字节时读出来的是:* 小端读小端:0x 12 34 56 78* 大端读大端:0x 12 34 56 78* 小端机器上读大端数据:0x 78 56 34 12* */
对uchar数组进行取操作
定义一个uint8_t的数组观察起内部内存
char _32low[] ={ 0x12,0x34,0x56,0x78,0x90,0x11,0x12,0x13};
从下方图片可以看到数组[0]的地址比数组[3]的地址低
尝试使用uint32_t 每次区 1、2、3、4byte数据
char _32low[] ={ 0x12,0x34,0x56,0x78,0x90,0x11,0x12,0x13};//小端char abca[8];reverseArray((char*)&_32low,abca,8);//这里模拟讲小端转为大端 变为{0x78,0x56,0x34,0x12,0x13,0x12,0x11,0x90}//注意数组左侧为低地址、右侧为高地址memcpy(&_32high1,abca+0,1);//由于我们是小端机器,那么memcpy后变成 0x78//注意0x56是高地址,所以在0x78的前面memcpy(&_32high2,abca+0,2);//由于我们是小端机器,那么memcpy后变成 0x5678memcpy(&_32high3,abca+0,3);//由于我们是小端机器,那么memcpy后变成 0x345678memcpy(&_32high4,abca+0,4);//由于我们是小端机器,那么memcpy后变成 0x12345678uint8_t _81;uint16_t _161;uint32_t _321;memcpy(&_81,abca+2,1);//由于我们是小端机器,那么memcpy后变成 0x34memcpy(&_161,abca+2,2);//由于我们是小端机器,那么memcpy后变成 0x1234memcpy(&_321,abca+2,4);//由于我们是小端机器,那么memcpy后变成 0x12131234
提升
经过上面的介绍一定对大小端有了一定的了解,那么接下来进行的是 memcpy数组到另一个数组
uchar[]给uchar[]
char _32low[] ={ 0x12,0x34,0x56,0x78,0x90,0x11,0x12,0x13};//小端
char abca[8];memcpy(abca,_32low,8);
//abca得到的是[0]=0x12 [1]=0x34 。。。原因是从低地址memcpy到高地址
uint32_t[]给uint32_t[]
#pragma pack(1)uint32_t u32[8]={0x12345678,0x90111213,0x14151617,0x18192021,0x22232425,0x26272829,0x30313233,0x34353637};
#pragma pack(0)uint32_t u32new[8];memcpy(u32new,u32,sizeof(uint32_t)*8);//分析一下 //地址 1000 1001 1002 1003//数据 0x13 0x12 0x11 0x90//memcpy时我们是小端的机器所以从小端memcpy(&_321,u32new+1,4);//因为我们小端设备,所以memcpy时会从低地址读写到我们的低地址 所以写出来是0x90111213
uint32_t[]给uint8_t[]
#pragma pack(1)uint32_t u32[8]={0x12345678,0x90111213,0x14151617,0x18192021,0x22232425,0x26272829,0x30313233,0x34353637};
#pragma pack(0)memcpy(abca,u32,8);//可以自行计算[结果在下方三行处]//将得到->abca[0]=0x78 [1]=0x56 [2]=0x34 [3]=0x12 [4]=0x13 [5]=0x12 [6]=0x11 [7]=0x90
本项目代码
#include <WinSock2.h>
#include <QDebug>
#include <iostream>
#pragma comment(lib,"ws2_32.lib")
bool isLittleEndian() {uint16_t number = 0x1234;uint8_t *ptr = reinterpret_cast<uint8_t*>(&number);return (ptr[0] == 0x34);
}
void MainWindow::reverseArray(char *src, char *dest, uint length)
{for(uint i=0; i<length/4; i++){dest[4*i+0] = src[4*i+3];dest[4*i+1] = src[4*i+2];dest[4*i+2] = src[4*i+1];dest[4*i+3] = src[4*i];}
}
/*** 前* 言:* 在讨论 memset 和 memcpy 函数时,它们的最小单位是以字节(byte)为单位。** 为什么要区分 大小端字节序* 如:0x12345678(此种写法 左侧高字节 右侧低字节)* 地址显示: 0000 0001 0002 0003* 小端显示: 78 56 34 12* 大端显示: 12 34 56 78* 我们知道当我们 memset或memcpy从内存读数时都是从低地址往出读的* 注意:我们读出来数据时是从低位读的,* 那么小端模式下(读出来的低地址数据在低位):读出来的数写到 目的地址的时候也是依次向右挤的(头插法)* 在大端模式下(读出来的低地址数据在高位):读出来的数写到 目的地址的时候是依次向右添加的(尾插法)* 此时当我们memset 1字节时读出来的是:* 小端读小端:0x 78* 大端读大端:0x 12* 小端机器上读大端数据0x 12* * 此时当我们memset 2字节时读出来的是:* 小端读小端:0x 56 78* 大端读大端:0x 12 34* 小端机器上读大端数据:0x 34 12* * 此时当我们memset 3字节时读出来的是:* 小端读小端:0x 34 56 78* 大端读大端:0x 12 34 56* 小端机器上读大端数据:0x 56 34 12* * 此时当我们memset 4字节时读出来的是:* 小端读小端:0x 12 34 56 78* 大端读大端:0x 12 34 56 78* 小端机器上读大端数据:0x 78 56 34 12* */
void MainWindow::on_pushButton_5_clicked()
{<地址从左到右依次递增
#pragma pack(1)char _32low[] ={ 0x12,0x34,0x56,0x78,0x90,0x11,0x12,0x13};//小端uint32_t _32low_t ;memcpy(&_32low_t,_32low+0,4);//由于小端 memcpy之后变为0x78563412uint32_t _32high1,_32high2,_32high3,_32high4 ;uint8_t _81;uint16_t _161;uint32_t _321;char abca[8];reverseArray((char*)&_32low,abca,8);//这里模拟讲小端转为大端 变为{0x78,0x56,0x34,0x12,0x13,0x12,0x11,0x90}memcpy(&_32high1,abca+0,1);//由于我们是小端机器,那么memcpy后变成 0x78memcpy(&_32high2,abca+0,2);//由于我们是小端机器,那么memcpy后变成 0x5678memcpy(&_32high3,abca+0,3);//由于我们是小端机器,那么memcpy后变成 0x345678memcpy(&_32high4,abca+0,4);//由于我们是小端机器,那么memcpy后变成 0x12345678memcpy(&_81,abca+2,1);//由于我们是小端机器,那么memcpy后变成 0x34memcpy(&_161,abca+2,2);//由于我们是小端机器,那么memcpy后变成 0x1234memcpy(&_321,abca+2,4);//由于我们是小端机器,那么memcpy后变成 0x12131234memcpy(abca,_32low,8);//abca得到的是[0]=0x12 [1]=0x34 。。。原因是从低地址memcpy到高地址
#pragma pack(0)#pragma pack(1)uint32_t u32[8]={0x12345678,0x90111213,0x14151617,0x18192021,0x22232425,0x26272829,0x30313233,0x34353637};
#pragma pack(0)uint32_t u32new[8];memcpy(u32new,u32,sizeof(uint32_t)*8);//分析一下//地址 1000 1001 1002 1003//数据 0x13 0x12 0x11 0x90//memcpy时我们是小端的机器所以从小端memcpy(&_321,u32new+1,4);//因为我们小端设备,所以memcpy时会从低地址读写到我们的低地址 所以写出来是0x90111213memcpy(abca,u32,8);//将得到->abca[0]=0x78 [1]=0x56 [2]=0x34 [3]=0x12 [4]=0x13 [5]=0x12 [6]=0x11 [7]=0x90qDebug()<<"_32low = "<<QString::number(_32low_t,16);qDebug()<<"_32high ="<<QString::number(_32high4,16);if (isLittleEndian()) {std::cout << "This system is Little Endian" << std::endl;} else {std::cout << "This system is Big Endian" << std::endl;}for(int i=0 ; i<10 ; i++){static uint ss = 0;ss++;qDebug()<<ss;}}
结语
- 如有问题欢迎指正