杂谈c语言——3.内存对齐

先看两个例子:

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个字节的内容。会出问题

  • 23
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 18
    评论
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值