结构体内存对齐的补充说明与总结

结构体内存对齐解析
本文详细阐述了结构体内存对齐的基本原理,包括默认对齐数、偏移值的概念及计算方法,并通过实例代码展示了如何计算结构体的大小。

在第一篇博客已经对结构体内存对齐进行了一些简单的说明,在这篇则对其进行一些总结和补充说明:

总结:结构体内存对齐中存在默认对齐数(不同平台不一致),VS中为8,Linux中为4,也可以自己设定,在VS中运用#program pack(4),可将8改为4,最后可以用         #program pack()取消;

1:必须了解偏移值,如图:


数字0、1、2、3、4、5、6、7、8等是偏移值,大的偏移值-小的偏移值==之间内存空间个数,例如:8=8-0,4=4-0,4=8-4等;

2.对于结构体的第一个变量成员从0偏移值进行对齐(如为char类型1个字节,则占用0~1这1块空间,为int类型4个字节占用0~4这4块空间),由此对齐第一个;

3.对于第二个变量成员对齐到它自身与默认对齐数VS---8中较小者的整数倍的偏移值上去(如为int类型4个字节则从4偏移值进行对齐,double类型8个字节从8这个偏移值进行对齐);

4.对于第三个、第四个等剩下的成员变量对齐规律与第二个变量成员规律一致;

5.变量成员都对齐以后,结构体总大小==所有变量成员其中的最大对齐数的整数倍。

由此规律,分析这一段代码得出:

typedef struct S
{
	char c1;
	int i;
	double d;
	char c2;
}S;
int main()
{
	printf("%d\n",sizeof(S));
	return 0;
}
结果不为14,17,而为24(c1从0偏移值开始对齐,占0~1,1~4之间空间浪费,i则从4偏移值开始对齐,占4~8,d从8偏移值开始对齐,占8~16,c2从16偏移值开始,占16~17,此时总大小为17,不为变量成员double d(最大对齐数8的整数倍),所以结构体总大小==24,17~24之间空间浪费),如图:

补充说明:

1.对于结构体嵌套结构体,如这段代码:

typedef struct T
{
	int i;
	double d;
}T;
typedef struct S
{
	char c1;
	int i;
	T j;
	char c2;
}S;
int main()
{
	printf("%d\n",sizeof(S));
	return 0;
}
结果为:

其对齐规律与上整体相同,在一个结构体中遇到另一个结构体类型变量,则进入到另一结构体中对于其成员变量以相同规律进行对齐,最后结构体总大小==两个结构体中所有成员变量中最大对齐数的整数倍;
2.对于结构体中数组成员,如这段代码:

typedef struct S
{
	char c[3];
	int i;
}S;
int main()
{
	printf("%d\n",sizeof(S));
	return 0;
}
结果为:

上一段代码中,定义了char c[3],相当于定义了三个char类型成员,(若为int[4],相当于定义了四个int 类型的成员),然后其对齐规律与上总结一致。


### C语言中结构体内存对齐规则详解 在C语言中,结构体内存对齐是为了提高访问效率以及满足硬件架构的要求。以下是关于结构体内存对齐的主要规则: #### 1. 成员变量的对齐方式 每个成员变量都会按照其自身的大小或者指定的对齐属性进行对齐。如果未显式设置对齐参数,则由编译器决定,默认情况下通常是该类型大小的最小倍数[^1]。 例如,`int` 类型通常需要按 4 字节边界对齐,而 `char` 类型则只需按 1 字节边界对齐。 #### 2. 结构体整体对齐原则 整个结构体的大小必须是内部最大成员对齐值的整数倍。这意味着即使最后一个字段之后存在填充字节,也会被保留以确保总体积符合这一条件[^3]。 #### 3. 计算实例分析 考虑如下两个例子来具体说明这些规则的应用情况: ##### 练习1 ```c struct S1 { char c1; int i; char c2; }; printf("%d\n", sizeof(struct S1)); ``` 在此定义中: - `c1` 占用 1 字节,并位于偏移量为 0 的位置; - 接下来的 `int i` 需要 4 字节并对齐4 字节边界,因此在其前会有 3 字节的填充区使起始地址成为下一个最近的 4 的倍数的位置; - 紧随其后的 `c2` 尽管只需要单个字节的空间,但由于前面已经进行了必要的调整操作,这里可以直接放置于第 9 字节处; - 最终考虑到全局一致性需求——即总的尺寸应当能被最大的基本单位(这里是 4)所除尽无余数,所以在最后还需额外增加三个空白区域作为补充,从而得到最终的结果应该是 12 字节[^2]。 ##### 练习2 ```c struct S2 { char c1; char c2; int i; }; printf("%d\n", sizeof(struct S2)); ``` 在这个版本里: - 由于连续两个字符仅需各占一位即可完成布局安排工作,故它们可以紧挨着彼此依次排列下来分别占据头两格空间; - 对应到第三个组成部分也就是那个整形对象来说呢?因为之前累积起来的有效载荷刚好凑成了一个完整的四单元组群形式呈现出来啦~这样一来的话就不必再另行添加任何多余的间隔符之类的东东咯!于是乎我们便能够轻松得知此时此刻这个特定组合的整体容量正好等于八个比特位长度哦😊【注意这里的解释稍作简化处理以便更容易理解】[^2] --- ### 总结 综上所述,掌握好以上提到的各项要点对于我们深入理解和灵活运用C语言当中的这种机制至关重要。合理利用它可以有效减少不必要的资源浪费现象发生的同时还能显著提升程序执行速度等方面表现效果!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值