部分内容转载自:https://blog.csdn.net/humanking7/article/details/81057648
1. 使用union判断cpu大小端
大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。
小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。
Union 的特性是同一时刻只有一个成员有效,且所有的成员有一个相同的开始地址。联合体的访问不论对哪个变量的存取都是从 union 的首地址位置开始,所以可以用union来测试系统的大小端。
例:
当test.i=1时,数据是00000000,00000000,00000000,00000001
大端模式时,00000001是数据的低位,存储在高位地址中,存储如下,00000000,00000000,00000000,00000001,此时读取test.c,读取存储空间的第一个字节就是00000000,所以test.c=0说明是大端。
小端模式时,00000001是数据的低位,存储在低位地址中,存储如下,00000001,00000000,00000000,00000000,读取第一个字节就是00000001。所以test.c=1就是小端存储。
#include<iostream>
using namespace std;
int main()
{
union
{
int i;
char c;
}test;
test.i=1;
if(test.c) cout<<"小端\n";
else cout<<"大端\n";
system("pause");
return 0;
}
2假设我们要通过串口/UDP与下位机进行数据交互,数据协议为:
2.1 用union定义传输协议
//signed
typedef signed char int8;
typedef short int16;
typedef int int32;
typedef long long int64;
//unsigned
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned long long uint64;
#pragma pack(push)
#pragma pack(1)//单字节对齐
typedef struct
{
uint8 Head;//占1个字节
uint8 data1_c;//占1个字节
float data2_f;//占4个字节
uint16 data3_u16;//占2个字节
double data4_d;//占8个字节
int data5_int;//占4个字节
uint8 checkSum;//占1个字节
}ST_protocol;//一共占了21个字节
//用于传输的联合体变量
typedef union
{
char buf[21];
ST_protocol data;
}UnData;//用于传输的联合体变量
#pragma pack(pop)
2.2 赋值&发送
cout << "size(ST_protocol) : " << sizeof(ST_protocol) << endl;
cout << "size(UnData) : " << sizeof(UnData) << endl;
// 给传输数据赋值
UnData sendData;
sendData.data.Head = 0x55;//占1个字节
sendData.data.data1_c = 'A';//占1个字节
sendData.data.data2_f = 0.93;//占4个字节
sendData.data.data3_u16 = 0xAABB;//占2个字节
sendData.data.data4_d = 1.9934;//占8个字节
sendData.data.data5_int = 7;//占4个字节
// 校验
uint8 chkSum = 0;
for (int i = 0; i < 21-1; i++)
{
chkSum += (uint8)(sendData.buf[i]);
}
sendData.data.checkSum = chkSum;//占1个字节
// 发送数据
// write(const char* buf, const int len)
len = sizeof(sendData);
write(sendData.buf, len);//发送
2.3 接收&解析
UnData revData;
receive(revData.buf);//接收数据
// 解析
uint8 chkSum = 0;
for (int i = 0; i < 21-1; i++)
{
chkSum += (uint8)(revData.buf[i]);
}
if (chkSum == revData.data.checkSum
&& 0x55 == revData.data.Head)
{//接收成功
//解析出来的数据
revData.data.data1_c;
revData.data.data2_f;
revData.data.data3_u16;
revData.data.data4_d;
revData.data.data5_int;
}