结构体内存拷贝与#parama pack (1)
1. 发现问题:
串口在发送命令之前,需要利用结构体(易读,且容易定位)来填充发送命令的内存,发现了此问题:
#include <iostream>
// --------此处标记为A
typedef struct AirCmd
{
unsigned char ucAddr;
unsigned short ucFunc;
}Struct_AirCmd;
struct T_PARAMS
{
unsigned char version;
unsigned char sum;
short offset;
unsigned char type;
short threshold;
unsigned char level;
};
int main()
{
Struct_AirCmd a = {0x01, 0x0304};
char buf[4] = {0};
memcpy(buf, &a, sizeof(a));
printf("sizeof(Struct_AirCmd) = %d\n", sizeof(Struct_AirCmd));
printf(" %x %x %x %x\n", (unsigned char)buf[0], (unsigned char)buf[1], buf[2], buf[3]);
struct T_PARAMS t_DevPara=
{
0x01,
0x02,
0x0304,
0x05,
0x0607,
0x08
};
unsigned char para_Arry[100];
memcpy(para_Arry, &t_DevPara, sizeof(t_DevPara) );
printf("sizeof(t_DevPara) = %d\n", sizeof(t_DevPara));
for (int i =0; i < sizeof(t_DevPara); i++)
{
printf("%x ", para_Arry[i]);
}
printf("\n");
while(1);
}
结果为
sizeof(Struct_AirCmd) = 4
1 cc 4 3
sizeof(t_DevPara) = 10
1 2 4 3 5 cc 7 6 8 cc
可以发现:
1)编译器认为结构体里面最小单元长度为short,即就是2,因此 sizeof(t_DevPara) 为10,而不是8或者 12;
2)此机器为 小端模式,低位在前地存放在内存中;
3)当编译器 认为需要字节对齐时候,将自行填充某个值,某个值未知(此处为0xcc,其他地方可能为0x00) 这个可能跟随机;
另外:如果内存为01 02,则拷贝到结构体中则为 0x0201;
2、解决问题:
编译器主动了改动我们的命令,如何避免其被改变呢?也就是让编译器认为最小单元为 1, 这样也不会进行字节对齐而导致填充。
这时候就用到 #param pack (1) ,可以将此处拷贝到上面所说的 A标志处,结果为:
sizeof(Struct_AirCmd) = 3
1 4 3 0
sizeof(t_DevPara) = 8
1 2 4 3 5 7 6 8
可以看到,填充问题已经解决,但是应该注意到 大小端模式仍然存在,这个在赋值时候特别注意。最好,拷贝之后,打印出来,确定 低位 在前.