马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
先看两个例子:- typedef struct S {
- int a;
- double b;
- char c;
- }S;
- typedef struct B {
- int a;
- char b;
- double c;
- }B;
- int main() {
- printf("S : %d\n", sizeof(S));
- printf("B : %d\n", sizeof(B));
- return 0;
- }
复制代码 效果为:
S:24;
B:16:
可见差异,简单来说就是按照成员的界说序次,依次为其分配内存,分配内存的起始偏移位置应该是选定对齐数的整数倍,末了布局体变量所占巨细应该是成员最大对齐数的整数倍。
1.对齐原则
内存对⻬规则
• 第⼀个成员在与布局体偏移量为0的地点处。
• 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地点处。
• 注意:对⻬数 = 编译器默认的⼀个对⻬数 与 该成员⼤⼩的较⼩值。
• VS中默认的对⻬数为8
• 布局体总⼤⼩为:最⼤对⻬数(全部变量范例最⼤者与默认对⻬参数取最⼩)的整数倍。
• 假如嵌套了布局体的环境,嵌套的布局体对⻬到⾃⼰的最⼤对⻬数的整数倍处,布局体的团体⼤⼩ 就是全部最⼤对⻬数(含嵌套布局体的对⻬数)的整数倍。
举例证明- //练习1.
- struct A {
- char c;
- int i;
- char b;
- };
-
- int main(){
- printf("%d\n",sizeof(struct A));
- return 0;
- }
复制代码 布局体成员变量分配内存的详细过程:
1.起首:char c为第一个成员变量,遵照第一条规则,char c从偏移量0开始,占1个字节,指针指向下一个偏移地点1
2.接下来存放int i, 但偏移地点 “1” 并不是对齐数4的整数倍
对齐数4来自(对齐数 = 编译器默认的一个对齐数 与 该成员巨细的较小值。)规则2,成员变量2是int范例,巨细为4字节,在VS中,编译器默认对齐数为8,8与4的较小值为4,以是成员变量2的对齐数为4。
那么指针须要移动到对齐数4的整数倍,即偏移量4地点处,开始存放int i 占4个字节,且偏移量1~3为空闲区,浪费了。
3.接下来指针指向了偏移地点9,第三个成员变量char b的对齐数是1,偏移9是对齐数1的整数倍,符合条件,存放char b,占一字节,指针指向偏移10地点,由第三条规则可知,. 布局体总巨细为最大对齐数(每个成员变量都有一个对齐数)的整数倍,struct A最大对齐数是int i的对齐数4,那么现偏移10并不是对齐数4的整数倍,指针继续向下探求符合条件的偏移地点,末了指针指向偏移12,12是4的整数倍,符合规则,那么偏移竣事。
效果共占12字节,内存中浪费了6个字节。
2.强化训练
- struct S3
- {
- double d;
- char c;
- int i;
- };
-
-
- struct S4
- {
- char c1;
- struct S3 s3;
- double d;
- };
-
- int main(){
- printf("%d\n", sizeof(struct S4));
- return 0;
- }
-
复制代码 由对齐原则可知sizeof(s3)=16;
盘算sizeof(s4)
训练4.布局体内存分配过程:
1.起首:char c1为第一个成员变量,遵照第一条规则,char c从偏移量0开始,占1个字节,指针指向下一个偏移地点1
2.其次,第二个成员变量为布局体S3,分析是嵌套布局体,通过刚才对S3的布局体巨细可知是16字节,且S3中最大对齐数为8,通过规则4可知,现指针指向的偏移地点1并不是对齐数8的整数倍,以是指针须要向后跳转,直到指针指向偏移量为8的地点,才符合要求,开始存放struct S3成员变量,共16字节
3.末了,指针指向偏移量为24的地点处,末了一个成员变量为double d,d的对齐数为8,偏移地点“24”是对齐数8的整数倍,以是开始存放double d,占8字节。
如今指针指向了偏移量为32的地点,32是整个布局体最大对齐数8的整数倍,偏移竣事,布局体S4共占32字节,浪费了7个字节(偏移地点1~7)。
3.内存对齐的缘故起因
1. 不是全部的硬件平台都支持随意地点访问,有些硬件平台cpu只能从指定地点处读取指定巨细的数据,镌汰了非常抛出。
!!!!!!!!!!!
第一个由于内存对齐,固然ch只有1字节,但浪费3个字节 可以包管只读取到ch (不读到i)
第二个由于内存不对齐,会访问到ch和i的前3个字节的内容。会出标题
|