sizeof 和 alignment(对齐)
1: alignment的定义
alignment指的是对象的开始地址必须满足条件:
>>#pragma pack(push, 1)
<<任何地址
>>#pragma pack(push, 2)
<<偶数地址
>>#pragma pack(push, 4)
<<地址必须是4的倍数
>>#pragma pack(push, 8)
<<地址必须是8的倍数
2: 基本类型T的alignment(T)
对齐值就是上面所说的1, 2, 4, 8
现在对应于每个类型T, 都有一个alignment(T)和T对应,
这个对应关系究竟如何呢:
(以下针对我们现在所碰到的编译器而言)
<< char --> 1 (永远是1)
<< short
#pragma pack(1) --> 1
#pragma pack(2) --> 2
#pragma pack(4) --> 2 // 呵呵,这里是关键
... --> 2
<< int
#pragma pack(1) --> 1
#pragma pack(2) --> 2
#pragma pack(4) --> 4 // 呵呵,这里是关键
... --> 4
...
这里就有了一个概念, 我们尚且将其命名为
internal_PACK(T):
internal_PACK(char) = 1
internal_PACK(short) = 2
internal_PACK(int) =4
internal_PACK(int64) = 8
...
和当前编译器的对齐方式无关。
编译其当前设置的#pragma pack(n)值我们命名为
PACK (= n)
那我们就有公式:
if (internal_PACK(T) < PACK)
alignment(T, PACK) = internal_PACK(T)
else
alignment(T, PACK) = PACK
下面的这个对任何类型T都成立:
alignment(T) <= PACK --------------------------------#1
3 struct(or class)类型ST的alignment(ST)
alignment(ST) = max { alignment(T) | T 是ST的data member 的类型 }
4 举例
<<
#pragma pack(1)
struct A
{
....
};
由#1, 在pack(1)的情况下所有的 alignment(type)≡1
<<
#pragma pack(4)
struct A
{
char ch;
short sh;
};
alignment(ch) = 1
alignment(sh) = 2
alignment(A) = 2
<<
#pragma pack(8)
struct A
{
char ch;
int n;
char ch;
};
alignment(n) = 4
alignment(A) = 4
<<
#pragma pack(2)
struct A
{
char ch;
int n;
char ch;
};
alignment(n) = 2
alignment(A) = 2
5: sizeof(T)
<<
对基本类型来说
sizeof(T) = internal_PACK(T)
<<
对结构类型ST来说
把最后一个数据成员m_last去掉后形成的结构叫ST~
sizeof(ST) = sizeof(ST~) + last_size + patch
其中
<<
last_size = member_patch + sizeof(m_last)
member_patch = [sizeof(ST~) 到 比它的alignment(m_last)倍数的最小距离] ;
<<
patch = [sizeof(ST~) + last_size到比它大的alignment(ST)倍数的最小距离]
其中
<<
member_patch是因为m_last要地址对齐alignment(m_last)
<<
patch 是因为如果声明一个数组的话:
ST st[2];
为了满足
1: st[1] 地址alignment(ST)对齐
2: sizeof(st) = sizeof(st1) + sizeof(st2)
关键是第二条
所以需要patch把余下的空间补满。