结构体类型大小的计算
我们可以使用sizeof计算变量,例如可以用sizeof(int)计算整形的大小为四个字节。
我们知道一个int类型的变量大小为四个字节,一个char类型的变量大小为一个字节。
那么,如果我们创建一个包含int a,char b类型的结构体类型struct s,此时struct s所占的内存是多少呢?按照我们的正常思维,我们会把int类型和char类型的大小直接相加,即struct s所占内存是五个字节,然而事实真的如此吗?我们再VS上进行验证。
#include<stdio.h>
int main()
{
struct s
{
int a;
char b;
};
printf("%d", sizeof(struct s));
return 0;
}
运行结果如下:
奇怪的是,运行结果不为5,而为8,为什么呢?
原来,结构体在内存中的存储并不是简单的连续存储,而是遵从着一定的规则进行存储。
结构体的对齐规则
结构体的对齐规则如下:
1. 第一个成员在与结构体变量偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。(VS中默认的值为8)
3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整
体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
例一、我们以结构体类型struct s1为例:
struct S1
{
char c1;
int i;
char c2;
};
c1大小为1个字节,作为第一个成员存储在偏与结构体变量移量为0的地址(占用0)
i大小为4个字节,对齐数为4,由于要对齐到4的整数倍的地址处,最近的即为偏移量为4的地址(占用4,5,6,7)
c2大小为1个字节,对齐数为1,同i对齐到1的整数倍的地址,最近的即为偏移量为8的地址(占用8)
目前结构体大小为九个字节,由于结构体总大小为最大对齐数的整数倍,即为4的整数倍,9个字节不足,至少要12个字节
综上所述,s1类型大小为12个字节
例二、我们再以嵌套结构体的情况为例,即以结构体类型struct s3为例:
struct S2
{
double d;
char c;
int i;
};
struct S3
{
char c1;
struct S2 s2;
double d;
};
c1大小为8个字节,作为第一个成员存储在偏与结构体变量移量为0的地址(占用0)
struct s2的最大对齐数为8,由于嵌套的结构体对齐到自己的最大对齐数的整数倍处,所以struct s2对齐到偏移量为8的地址(占用8~23)(易得s2占用16个字节)
d大小为8个字节,对齐数为8,对齐至偏移量为24的地址处(占用24~31)
目前结构体大小为32个字节,最大对齐数为8,,结构体总大小为最大对齐数的整数倍,符合要求
综上所述,s3类型大小为32个字节
采用内存对齐的原因
1. 平台原因(移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2. 性能原因:
数据结构(尤其是栈)应该尽可能地在自然边界上对齐。
原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
总体来说,结构体的内存对齐是拿空间来换取时间的做法。
文章讨论了C/C++中结构体内存对齐的规则,解释了为何sizeof(structs)不等于成员变量大小之和,介绍了编译器如何按照对齐规则调整结构体的内存布局,以及内存对齐对于平台兼容性和性能优化的重要性。
520

被折叠的 条评论
为什么被折叠?



