在用sizeof运算符求算某结构体所占空间时,并不是简单地将结构体中所有元素各自占的空间相加,这里涉及到内存字节对齐的问题。
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对结构体首地址的偏移量都是成员大小的整数倍;
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍。
类型 | int | short | long | char | bool | float | double | 指针 | 枚举 |
字节 | 4 | 2 | 4 | 1 | 1 | 4 | 8 | 4 | 4 |
下面看一下sizeof在计算结构体大小的时候具体是怎样计算的:
1.test1 空结构体
typedef struct node
{
}S;
则sizeof(S)=1。
2.test2
typedef struct node1
{
int a;
char b;
short c;
}S1;
则sizeof(S1)=8。(int)4+(char)1+(填充)1+(short)2=8,且能被(成员最宽类型)4整除。
4.test4 含有静态数据成员
typedef struct node3
{
int a;
short b;
static int c;
}S3;
则sizeof(S3)=8。(int)4+(short)2=6+(填充)2=8,能被(成员最宽类型)4整除。
这里结构体中包含静态数据成员,而静态数据成员的存放位置与结构体实例的存储地址无关(注意只有在C++中结构体中才能含有静态数据成员,而C中结构体中是不允许含有静态数据成员的)。
5.test5 结构体中含有结构体
typedef struct node4
{
bool a;
S1 s1;
short b;
}S4;
则sizeof(S4)=16。(bool)1+(填充3)+(S1)8+(short)2=14+(填充)2=16,能被(成员最大宽度S1的宽度)4整除。
S1占8字节,而S1中最长数据类型为int,占4个字节。
6.test6
若在程序中使用了#pragma pack(n)命令强制以n字节对齐时,默认情况下n为8。则比较n和结构体中最长数据类型所占的字节大小,取两者中小的一个作为对齐标准。
如果在程序开头使用命令#pragma pack(4),对于下面的结构体
typedef struct node5
{
bool a;
S1 s1;
double b;
int c;
}S5;
则sizeof(S5)=24。因为强制以4字节对齐,而S5中最长数据类型为double,占8字节,因此以4字节对齐。在内存中存放方式为:
|-----------a--------| 4字节
|--------s1----------| 4字节
|--------s1----------| 4字节
|--------b-----------| 4字节
|--------b-----------| 4字节
|---------c----------| 4字节