结构体对齐问题

来源:互联网 发布:java xml生成pdf 编辑:程序博客网 时间:2024/05/17 06:42

结构体的成员变量对齐问题:

在嵌入式开发中,多多少少都要遇到这个结构体对齐的问题,特别是某些平台,一不对齐就crash。
还有就是和pc端软件共同协作时,更要统一结构体变量的对齐,否则就牛头不对马嘴了。


今天,就来总结下结构体到底是怎么对齐的。
这个对齐问题可以总结为两个问题点:
1. 成员变量的存放起始地址的确定,也就是相对于结构体起始地址的偏移量。
2. 整个结构体变量的大小
在C/C++中,我们可以用 #pragma pack(n)来定义当前环境的对齐方式(按多少个字节对齐),
我暂且把它叫做pack值吧

一、没有指明pack的情况下

当系统没有显示指定pack值时(一般默认按4字节对齐),可以认为当前环境的pack值为max(sizeof(member))
即取所占内存最大的成员变量的字节长度,

struct st{    char a;    short b;    int   c;}

我们可以认定pack值就是sizeof(int),也就是4字节对齐。
ok,现在确定了环境了的pack值后,接下来确定每个成员变量的起始地址
以上面st为例,
对于变量a来说,偏移量就是0,这个没什么疑问
对于b,由于b占两个字节,这时候b的起始地址是从多少开始呢?
先引入一个K,K=min(sizeof(mem),pack),这儿就是说K取当前环境pack值和成员变量内存大小之间的较小值。
这儿,sizeof(b)=2,pack为4,则K=2,即b要从2字节对齐的地址存放,由于a占了一字节,所以要空一个字节出来,接下来才是放变量b

同理,c的存放地址是4字节对齐。
确定好所有成员变量的起始地址后,就能确认整个结构体变量的大小了,即就是当前环境pack值的整数倍。
来几个例子:

struct st{    char a;    short b;    int   c;}sizeofstruct st)= 8
struct st{    short a;    short b;    int   c;}sizeofstruct st)= 8
struct st{    short a;    char b;    double c;}sizeofstruct st)= 16

二、当指定了pack值时

如#pragma pack(N),则要比较下到底该用几字节对齐。新的环境pack值为:pack=min(N,max(sizeof(mem)))
举例说明,#pragma pack(4),还是以上面的st结构体为例,可以得出pack=min(4,4),还是4.
巧合?。。。那我们定义#pragma pack(1) 呢?则pack=min(1,4) pack就为1了,也就是1一字节对齐。
确定pack后,怎么算成员变量的起始地址和结构体大小就和上面一样了。
例子:

#pragma pack(1)struct st{    short a;    char b;    double c;}sizeofstruct st)= 11

说明:
1、当成员变量是数组时,把数组当成多个变量来看,而不要看做一个整体。
如:

struct st{    char a[3];    int  b;}

把数组当成3个char型的变量就行了。
2、#define OFFSET(Type, member) (size_t)&( ((Type*)0)->member)
这个宏可以求出成员变量相对于结构体的偏移量

1 0