一 原理
由于存储变量时地址对齐的要求,编译器在编译程序时会遵循两条原则:
【原则1】结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
【原则2】结构体大小必须是所有成员大小的整数倍。
结构体总大小等于最后一个成员的偏移量加上其大小
二 实例
例1 计算结构体的大小
struct A
{
int a;
char b;
char c;
};
【解析】利用sizeof 计算,结果为8。记偏移量为ref,大小为size:
struct A { int a;//ref_a=0,size_a=4 char b;//ref_b=ref_a+size_a=4,size_b=1 char c;//ref_c=ref_b+size_b=5,size=1 };若不考虑字节对齐,总大小为ref_c+size_c=6。根据【原则2】,6不是int类型大小的倍数,故补齐2,大小为8。
例2 计算结构体的大小
struct B
{
char a;
short b;
char c;
};
【解析】利用sizeof 计算,结果为6。记偏移量为ref,大小为size:
struct B { char a;//ref_a=0,size_a=1 short b;//ref_b=2,size_b=2,若不考虑字节对齐,ref_b=ref_a+size_a=1。根据【原则1】,偏移量1不是short的倍数,故补1 char c;//ref_c=ref_b+size_b=4,size_c=1 };若不考虑字节对齐,总大小为ref_c+size_c=5。根据【原则2】,5不是short类型大小(size_b=2)的倍数,故补齐1,大小为6。
例3 计算结构体的大小
struct C
{
int a;
char b;
short c;
};
【解析】利用sizeof 计算,结果为8。记偏移量为ref,大小为size:
struct C { int a;//ref_a=0,size_a=4 char b;//ref_b=ref_a+size_a=4,size_b=1 short c;//ref_c=6,zize_c=2,若不考虑字节对齐,ref_c=ref_b+size_b=5。根据【原则1】,5不是short类型大小的倍数,故补齐1 };总大小为ref_c+size_c=8,总大小满足【原则2】不需要补齐。
【内存对齐的应用】
(1) 程序的可移植性
程序在不同的操作系统中移植,需要考虑内存对齐。
(2) 较少内存损失
在建立结构时,考虑字节对齐,可以使结构尽可能占用少的内存。不对内存的成员进行重排以减小因对齐带来的损失。