昨天以前,我以为自己理解了字节对齐。
昨天下午开始,我对这个问题表现了迷茫,因为我的理解,昨天下午硬是没有搞定。
今天再去网上搜索一下,终于,我觉得我现在理解了字节对齐。
//#pragma pack(4)
typedef struct _VoltageProtection_
{
unsigned char Enable;
//char kfek1;
unsigned short TimeForCMS;
unsigned short TimeForShutDown;
unsigned short Voltage;
//int fkessss;
unsigned short powerOnVoltage;
unsigned char PowerType;
//char kfek2;
unsigned short VoltageLoss;
unsigned short HighVoltage;
unsigned char reserve[64];
char devID[10];
}VolProtect_t;
//#pragma pack()
// CstcpserverApp 初始化
BOOL CstcpserverApp::InitInstance()
{
...
int sie = sizeof(VolProtect_t);
...
}
以上代码,我修改编译器的字节对齐选项(不选1字节对齐),则sie的值丝毫没有影响,一直坚定地输出为90。如果选择了4字节,那90显然不是4的倍数。
我预计编译时会插入两个字段进去,分别是kfek1、kfek2,这和我的预计相吻合。
我把前后的pragma打开,不管里面的值改成4,还是8,也不影响sie的值为90,晕了。
刚刚上网上搜索了一下字节对齐,一篇文章 http://www.cnblogs.com/dabiao/archive/2010/04/15/1712458.html,其中一句话“C编译器缺省的结构整体的自然对界条件为:该结构所有成员中要求的最大自然对界条件”。而且举了一个例子:
struct Test
{
char x1; // 成员x1为char型(其起始地址必须1字节对界),其偏移地址为0
char x2; // 成员x2为char型(其起始地址必须1字节对界,其偏移地址为1
float x3; // 成员x3为float型(其起始地址必须4字节对界),编译器在x2和x3之间填充了两个空字节,其偏移地址为4
char x4; // 成员x4为char型(其起始地址必须1字节对界),其偏移地址为8
};
由于x3为4个字节,所以整个结构体是按照4字节对齐的。这个很管用。于是我把我的结构中 fkessss 一行的注释符号去掉,把该字段加入到结构体的定义中,再编译运行,发现sie的值终于改变成96了!
我想我是理解了:
以结构中定义的最长的一个字段为最小的对齐单位,而且它不受编译选项 pragma 的影响。
喝水去了...