对齐系数:每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数。而对齐系数的确认是通过一个结构体中的最宽的基本数据类型来确认的。
通过一个例子说明结构体所占内存的大小。
struct st
{
int i;
short s;
char c;
int i1[3];
char c1[17];
};
cout<<"sizeof(st)="<<sizeof(st)<<endl;
解题过程:
1、首先,将最宽的数据类型的大小作为对齐模数,即整形数据的大小(4)
2、其次,通过数据成员对齐,求出成员总大小。
int型,长度4=4,按4对齐,offset=0 因为0%4=0,所以地址区间是[0,3]
short型,长度2<4,按2对齐,offset=4 因为4%2=0,所以地址区间是[4,5]
char型,长度1<4,按1对齐,offset=6 因为6%1=0,所以地址区间是[6,6]
int型,长度4=4,按4对齐,offset=7时,因为7%4!=0,所以需要加上填充字节,令offset=8,这时候,8%4=0,地址区间是[8,19]
char型,长度1<4,按1对齐,offset=20,因为20%1=0,所以地址区间是[20,36]
所以,求得的成员的总大小=37
3、再次,整体对齐系数=min(max(int,short,char),对齐模数)=min(max(4,2,1),4)=4
4、最后,整体大小(所占内存大小)=$(成员总大小)圆整$(整体对齐系数)=$(37) 圆整 $(4)=40
另一个简单的例子:
struct st
{
int i;
short s;//数据类型大小占两个字节,地址从4-5
int i2;//按4对齐,起始地址(offset)不可以是6,添加填充字节,使offset=8
char c;//占一个字节,起始地址从12开始
//成员总大小是13,对4圆整是16,故最终结果是16!!!
};
cout<<"sizeof(st)="<<sizeof(st)<<endl;
圆整:举例说明
举例说明:9 按 4 圆整 = 12
圆整的过程:从9开始每次加1,看是否能被4整除,这里9,10,11均不能被4整除,到12时可以,则圆整结束。也就是9一直加1,直到是的倍数为止。
后来又遇到了一个同样的问题,经过思考,明白了不少,首先看一下这个例子:
#include <iostream>
using namespace std;
typedef struct a
{
int ia;
float fa;
double da;
}a,array[20];
typedef struct b
{
array barray;//定义的是结构体struct a 数组
int ib;
}b;
void main()
{
cout<<sizeof(a)<<endl;
cout<<sizeof(array)<<endl;
cout<<sizeof(b)<<endl;
}
输出结果是:
16
320
328
看过上面的,可能对第一个第二个值好理解,但是第三个为什么是328而不是324,就不清楚了。如果大家把结构体a中的“double da”改成同样大小的“int da[2]”,看一下结果,就发现结果变成了324,为什么会这样呢?
原因就是在结构体b中,整体对齐系数是8而不是4,这个8是由结构体中的double类型得来的,所以,最后成员的总大小虽然是324,但是对整体对齐系数8圆整,就会得到整体大小是328。