
本文共 1480 字,大约阅读时间需要 4 分钟。
1
结构体所占空间的大小,并不是简单地将结构体内所有数据元素各自占的空间相加,这里涉及到内存字节对齐的问题。从理论上讲,对于任何变量的访问都可以从任何地址开始访问,实际上,为了提高存取速度,会进行字节对齐。这就需要各类型数据按照一定的规则在空间上排列,而不是顺序地一个接一个地排放。比如有些平台每次读都是从偶地址开始,一个int型(假设为32位)如果存放在偶地址开始的地方,那么一个读周期就可以读出,而如果存放在奇地址开始的地方,就可能会需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该int数据,显然在读取效率上下降很多。也是用空间换时间。
2
对齐的字节是多大呢?有两个依据,1是系统默认的规则,2是通过指令规定的。系统默认规则时,我们需要理解系统的规则,通过指令则是#pragma pack(n)来设定以n字节对齐方式。
3
规则1
结构体内对齐依据成员的最大字节占用,结构体的大小与成员的顺序有关。
在笔者Mac下(10.11.5 Xcode8.1) 64位环境下,数据类型所占字节type | sizeof |
---|---|
bool | 1 |
char | 1 |
short | 2 |
int | 4 |
float | 4 |
unsigned int | 4 |
long | 8 |
long long | 8 |
double | 8 |
指针 | 8 |
typedef struct testA{ char gender; short score; int age;};
age是int型,占用字节最大,故该结构体为4字节对齐,不够4个字节的也会占用4个字节,sizeof(struct testA)的值为8,
typedef struct testB{ char gender; int age; short score;};
也是4字节对齐,但sizeof(struct testB)的值为结果却为12,为什么呢?
这就是成员顺序的原因了,在结构体testA中布局如下 |gender(1) score(2)| |age(4)| 4字节对齐时,gender和score总和不超过4,可以放在一起 在结构体testB中布局如下 |gender(1)| |age(4)| |score(2)| gender+age的和超过4,需要重新对齐,score同理。规则2
结构体内包含子结构体时,在计算子成员的大小时作为字节对齐依据时,子结构体内成员的最大占用字节就是子结构体的占用字节,但子结构体具体的占用空间还是该结构体的实际空间。
typedef struct testC{ struct testB other; double money; short score;};
testB内最大字节占用是4个字节,而money占用8个字节。所以是8个字节对齐,sizeof(struct testC)大小为32。具体分配如下
other大小占了12位,在4字节对齐的情况下,在testC中依然占12位(4的倍数),在8字节对齐的情况下,就会占用16位(8的倍数)。 testB(16) money(8) score(8) 若将money改为int类型,由于testB内最大的占用是age的4个字节,大于money和short的2个字节,故4字节对齐,但testB仍占用12字节, sizeof(struct testC)大小为20位。总结 字节对齐是一种空间换时间的概念,编译器会对结构体进行处理,结构体的大小与成员类型和顺序有关,并不是简单将其成员大小相加的和。
发表评论
最新留言
关于作者
