在结构体(变量)
中,结构的各成员顺序排列存储,每个成员都有自己独立的存储位置。联合(union)变量
的所有成员共享同片存储区/内存
。因此联合变量每个时刻里只能保存它的某一个成员的值。
联合变量也可以在定义时直接初始化,但这个初始化
只能对第一个成员
进行。例如下面的描述定义了一个联合变量,并进行了初始化。
typedef union
{
char a;//占1个字节
float b;//占4个字节
double c;//占8个字节
int d;//占4个字节
}UData;
UData x1 = {5}; //只有x1.a被初始化
//总共UData这种类型的变量占有的大小为 8 个字节
union
中可以定义多个成员,union
的大小由最大的成员的大小决定,如上文中所示的联合体类型UData
的大小由所占空间最大的double c
变量决定;union
成员共享同一块大小的内存,一次只能使用其中的一个成员;因此,运用最后一个特性可以用联合(union
)来判断CPU的大小端(字节序
)。
static union
{
char chr[4];
unsigned long lng;
}Endian_Test = { { 'L', '?', '?', 'B' } };
#define Endianness ( (char)Endian_Test.lng )
用联合(union
)来判断CPU的大小端(字节序
):
#include <iostream>
using namespace std;
static union
{
char chr[4];
unsigned long lng;
}Endian_Test = { { 'L', '?', '?', 'B' } };
#define Endianness ( (char)Endian_Test.lng )
int main()
{
cout << "该电脑的字节序为:" << endl;
if ('L'==Endianness)
{
cout << "小端字节序 - Little Endianness" << endl;
}
else
{
cout << "大端字节序 - Big Endianness" << endl;
}
return 0;
}
在我电脑上运行的结果为:
该电脑的字节序为: 小端字节序 - Little Endianness
假设我们要通过串口/UDP与下位机进行数据交互,数据协议为:
//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)
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; 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);//发送
UnData revData;
receive(revData.buf);//接收数据
// 解析
uint8 chkSum = 0;
for (int i = 0; i < 21; 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;
}