一、结构体的内存对齐
int类型占用4字节,char类型占用1字节,short类型占用2字节,如果把它们放到结构体里,那结构体占用内存是不是4+1+2=7字节。 输出结果显示,结构体占用内存不是7字节,说明结构体里面的三个成员并不是在内存中紧密连续排列的。
(一).结构体内成员在内存中的偏移量
通俗来说,以结构体在内存中的第一个字节为标准,后面的内存单元比第一个字节大多少,那偏移量就是多少,如下图:
(二).测试结构体成员的偏移量
专门用来测结构体成员偏移量的函数是ofsetoff ( type,member ),返回值是偏移量,头文件是stddef.h
(三).根据偏移量画出结构体的内存布局
结构体占用12字节,所以画出12个字节,并根据偏移量,将结构体成员a,b,c放入:
(四).结构体内存对齐规则
编译器拥有一个对齐数,在VS平台上,对齐数是8;在gcc上对齐数等于该成员变量大小。以VS2022为例,结构体成员的对齐数取成员变量本身大小和编译器对齐数中较小的那一个,如下图:
规则一:结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处。
这个很容易理解,结构体第一个成员a占用第一个字节。
规则二:除第一个成员变量外的其他成员变量要对⻬到对⻬数的整数倍的地址处。
通俗说,a以外的成员变量,就是b和c,int类型的b要对齐到b本身大小整数倍的地方,就是偏移量是4的倍数;short类型的c要对齐到本身大小整数倍的地方,就是偏移量是2的倍数。
规则三:结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的 整数倍。
b的对齐数字是最大的4,所以结构体的大小是4的倍数,a,b,c已经占用了10个字节,所以还需要补充2个字节,即结构体大小是10+2=12字节(12是4的倍数)。
规则四构体S1内嵌构体S2,内嵌构体S2的偏移量是它自身成员的最大的对齐数。结构体S1的大小是S1全部成员所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。
举例如下图:结构体S1包含一个结构体S2
首先分析S2,S2内拥有最大对齐数的是成员double c,对齐数为8,画出内存图:
验证结构体S2占用的内存空间:
与图示一致,大小16字节。
接下来分析结构体S1
那么结构体S1中成员内最大对齐数是8,他的大小应该是8的倍数,测试:
结构体S1大小为32字节,是8的倍数,接下来画S1的内存图:
(五)结构体内存对齐的原因
原因一:平台原因
不是所有硬件平台都能访问内存中任意地址的,某些硬件平台只能在某些地址取得数据。
原因二:性能原因
如果访问未对齐的内存,处理器要做2次访问。假设一个处理器一次只能取4个字节,则地址必须为4的倍数,内存有一个char类型a和一个int类型b,如果内存未对齐:
总体来说:结构体的内存对⻬是拿空间来换取时间的做法。
所以在设计结构体的时候,既要满足对齐,又要节省空间,让占用空间小的成员尽量集中到一起。例如:
画出内存图: