
在上一篇博客《结构体详解:声明、使用与优化技巧》中,我们讨论了结构体的声明、使用……然而,在实际开发中,结构体的内存布局往往隐藏着更微妙的细节——比如为什么一个看似简单的结构体却占用了意料之外的内存空间?这背后正是内存对齐在起作用。 本文将深入剖析结构体内存对齐的规则,结合实例分析对齐对程序性能与空间的影响,并分享如何通过合理设计结构体来优化内存使用。
首先得掌握结构体的对齐规则:
struct S1
{
char c1;
int i;
char c2;
};
int main()
{
printf("%d\n", sizeof(struct S1));
return 0;
}解析:(注意每个成员都有对齐数)

练习2:
struct S2
{
char c1;
char c2;
int i;
};
int main()
{
printf("%d\n", sizeof(struct S2));
return 0;
}解析:

练习3:
struct S3
{
double d;
char c;
int i;
};
int main()
{
printf("%d\n", sizeof(struct S3));
return 0;
}解析:

练习4-结构体嵌套问题:
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;
}解析:

对于结构体对齐规则就到这,那为什么进行内存对齐?也就是为什么存在内存对齐呢?
大部分的参考资料都是这样说的:
总体来说:结构体的内存对齐是拿空间来换取时间的做法。 那在设计结构体的时候,我们既要满足对齐,又要节省空间,如何做到:
让占用空间小的成员尽量集中在一起
//例如:练习1与练习2
struct S1
{
char c1;
int i;
char c2;
};
struct S2
{
char c1;
char c2;
int i;
}S1 和 S2 类型的成员⼀模⼀样,但是 S1 和 S2 所占空间的大小(S1为12、S2为8)有了⼀些区别。
#pragma 这个预处理指令,可以改变编译器的默认对齐数。
咱们可以来试一试:
#include <stdio.h>
#pragma pack(1)//设置默认对⻬数为1
struct S
{
char c1;
int i;
char c2;
};
int main()
{
//输出的结果是什么?
printf("%d\n", sizeof(struct S));
return 0;
}这样的话,大小就为6了; 调试:

咱们也可以将默认对齐数修改回来:
#include <stdio.h>
#pragma pack(1)//设置默认对⻬数为1
struct S
{
char c1;
int i;
char c2;
};
#pragma pack()//取消设置的对1数,还原为默认
int main()
{
//输出的结果是什么?
printf("%d\n", sizeof(struct S));
return 0;
}对齐是硬件友好的契约,更是跨平台的护城河。 下次当sizeof结果出乎意料时,不妨画个内存布局图——真相就在偏移量的数字里!