struct
struct可以将一些相关联的数据打包成一个整体。既然提到了struct那么肯定就避免不了结构体,结构体的内存对齐。
1. 什么是结构体?
结构体是一系列类型数据的集合这些数据可能描述了一个物体。
2. 什么时候会用到结构体?
1. 当内置类型无法满足用户需求的时候,没有合适类型的时候,需要封装特定的类型
2. 当函数有多个参数时,或者函数的返回值过多的时候,需要封装特定的类型,将参数打包返回
3. 什么是结构体内存对齐?为什么存在内存对齐?内存对齐的规则是什么?
编译器为程序中的每一个数据单元安排在合适的位置上,从而导致了相同的变量,不同声明顺序的结构体的大小不同。 内存对齐存在的主要原因:
1. 平台原因:不是所有的硬件平台都可以访问任意地址上的任意数据,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出异常(这个为什么会抛出异常,不是很懂)
2. 性能原因:经过内存对齐后,CPU的内存访问速度大大提升,因为如果没有内存对齐的话,CPU在访问一个数据时可能会进行多次访问然后拼接在一起。
结构体的内存对齐规则: (看下面的规则)
1. 结构体的第一个成员存放在与结构体变量偏移量为0的地址处
2. 结构体的其他成员要对齐到对齐数的整数倍地址处。对齐数:编译器默认的一个对齐数与该成员大小中的较小值,VS默认的对齐数位8,Linux中默认值为4
3. 结构体的总大小最最大对齐数的整数倍
4. 如果一个结构体中嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍,结构体的大小就是所有最大对齐数(包含嵌套结构体的对齐数)的整数倍
5. 可以通过#pragma pack number设置对齐数
如何知道结构体中某个成员相对于结构体起始位置的偏移量?
//使用offsetof宏
size_t offsetof( structName, memberName )
---------------------
规则一.: 每个成员变量在其结构体内的偏移量都是成员变量类型的大小的倍数。
规则二: 如果有嵌套结构体,那么内嵌结构体的第一个成员变量在外结构体中的偏移量,是内嵌结构体中那个数据类型大小最大的成员变量的倍数。
规则三: 整个结构体的大小要是这个结构体内数据类型大小最大的成员变量的倍数。如果有内嵌结构体,那么取内嵌结构体中数据类型大小最大的成员变量作为计算外结构体整体大小的依据。
例子
typedef struct TEST{
int na;
char cb;
char cc;
int nd;
char cf;
struct TT{
int ng;
long long llh;
}tt;
char ci;
}test;
图一
如上图所示,根据规则一,nd在结构体内的位置必须满足是其自身数据类型大小的整数倍,且倍数要取满足条件的最小倍数。因为nd前三个成员变量总大小是6Bytes,nd作为int类型,其数据类型大小是4Bytes,满足条件的最小倍数是2,所以nd在结构体中的偏移量是8,故填充2Bytes。
根据规则二,ng作为内嵌结构体的第一个成员变量,它在外结构体中的偏移量要满足——其内嵌结构体中最大数据类型大小的倍数。在计算cf偏移量后,当前偏移量是13,而内嵌结构体中最大数据类型为long long,其大小为8,ng的偏移量必须是8的倍数,且取大于13的最小倍数,即2。所以ng前要填充3Bytes。
根据规则三,计算完ci后,当前偏移量是33。如果要满足test结构体的大小是其中最大数据成员类型大小的倍数,在此例中是内嵌结构体的成员变量llh,即8的倍数。所以要填充7Bytes。