先介绍一个相关的概念——偏移量。
偏移量指的是结构体变量中成员的地址和结构体变量地址的差。
结构体大小等于最后一个成员的偏移量加上最后一个成员的大小。
显然,结构体变量中第一个成员的地址就是结构体变量的首地址。因此,
struct stu1
{
int i;
char c;
int j;
};第一个成员i的偏移量为0。—定死的
第二个成员c的偏移量是第一个成员的偏移量加上第一个成员的大小(0+4),其值为4;
第三个成员j的偏移量是第二个成员的偏移量加上第二个成员的大小(4+1),其值为5。
实际上,由于存储变量时地址对齐的要求,编译器在编译程序时会遵循两条原则:
一、结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
二、结构体大小必须是所有成员大小的整数倍。
一、什么是字节对齐
一个基本类型的变量在内存中占用n个字节,则该变量的起始地址必须能够被n整除,即: 存放起始地址 % n = 0,那么,就成该变量是字节对齐的;对于结构体、联合体而言,这个n取其所有基本类型的成员中占用空间字节数最大的那个;
内存空间是以字节为基本单位进行划分的,从理论上讲,似乎对任何类型的变量的访问都可以从任何地址处开始,但实际情况是在访问特定类型变量的时候经常是从特定的内存地址处开始访问,这就需要各种类型的数据只能按照一定的规则在空间上排列,而不是顺序的一个接一个地排放;究其原因,是为了使不同架构的CPU可以提高访问内存的速度,就规定了对于特定类型的数据只能从特定的内存位置处开始访问;所以,各种类型的数据只能按照相应的规则在内存空间上排放,而不能顺序地、连续地、一个一个地排放;这就是内存对齐;
对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节。
这里面有四个概念值:
1.数据类型自身的对齐值:就是上面交代的基本数据类型的自身对齐值。
2.指定对齐值:#progma pack (value)时的指定对齐值value。
3.结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。
4. 数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中小的那个值。
结构体到底怎样对齐? 有人给对齐原则做过总结,具体在哪里看到现在已记不起来,这里引用一下前人的 经验(在没有#pragma pack 宏的情况下):
原则 1、数据成员对齐规则:结构(struct 或联合 union)的数据成员,第一个数据 成员放在offset 为0 的地方,以后每个数据成员存储的起始位置要从该成员大小的整数倍开 始(比如int 在32 位机为4字节,则要从4 的整数倍地址开始存储)。
原则 2、结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从 其内部最大元素大小的整数倍地址开始存储。(struct a 里存有struct b,b 里有char,int,double 等元素,那b 应该从8 的整数倍开始存储。) 原则
3、收尾工作:结构体的总大小,也就是 sizeof 的结果,必须是其内部最大成 员的整数倍,不足的要补齐。
拷贝构造函数
友元
多继承且有内嵌对象时的构造函数