前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >杂谈c语言——3.内存对齐

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

作者头像
用户11286441
发布2024-09-23 19:42:09
500
发布2024-09-23 19:42:09
举报
文章被收录于专栏:学习

先看两个例子:

代码语言:javascript
复制
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 • 结构体总⼤⼩为:最⼤对⻬数(所有变量类型最⼤者与默认对⻬参数取最⼩)的整数倍。 • 如果嵌套了结构体的情况,嵌套的结构体对⻬到⾃⼰的最⼤对⻬数的整数倍处,结构体的整体⼤⼩ 就是所有最⼤对⻬数(含嵌套结构体的对⻬数)的整数倍。

举例证明

代码语言:javascript
复制
//练习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.强化训练

代码语言:javascript
复制
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个字节的内容。会出问题

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-08-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.对齐原则 
  • 2.强化训练
  • 3.内存对齐的原因 
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档