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

相关推荐
寻找码源几秒前
【头歌实训:利用kmp算法求子串在主串中不重叠出现的次数】
c语言·数据结构·算法·字符串·kmp
Matlab精灵2 分钟前
Matlab科研绘图:自定义内置多款配色函数
算法·matlab
诚丞成11 分钟前
滑动窗口篇——如行云流水般的高效解法与智能之道(1)
算法
手握风云-20 分钟前
数据结构(Java版)第二期:包装类和泛型
java·开发语言·数据结构
带多刺的玫瑰2 小时前
Leecode刷题C语言之统计不是特殊数字的数字数量
java·c语言·算法
爱敲代码的憨仔2 小时前
《线性代数的本质》
线性代数·算法·决策树
熬夜学编程的小王2 小时前
【C++篇】深度解析 C++ List 容器:底层设计与实现揭秘
开发语言·数据结构·c++·stl·list
yigan_Eins2 小时前
【数论】莫比乌斯函数及其反演
c++·经验分享·算法
阿史大杯茶2 小时前
AtCoder Beginner Contest 381(ABCDEF 题)视频讲解
数据结构·c++·算法
陌小呆^O^2 小时前
Cmakelist.txt之win-c-udp-server
c语言·开发语言·udp