C/C++中的字节对齐,结构体对齐,alignment,简单易懂

关于对齐的内容事实上比较复杂,更详细的一篇文章参见:
https://blog.csdn.net/Sansipi/article/details/121597464
面试的时候一般只会问结构体对齐的规则是什么?只要记住下面的内容就ok了

1. 无pragma pack的结构体对齐规则

  • 分配内存的顺序是按照声明的顺序
  • 结构体内每一个数据成员的起始位置(第一个元素的起始位置看成0)都应当能被该成员的大小整除,如果不能,就需要对该成员的前一个成员进行填充
  • 对于整个结构体而言,还需要满足整个结构体的大小能被大小最大的成员的大小整除,如果不能,就在最后一个成员进行填充
    上面的规则比较拗口,下面是实例:
/*
S 的大小为24。
首先i,j, k的起始位置分别为0, 4, 6,但是6不能被8整除,
因此需要对j进行填充,填充到7,以8作为k的起始位置就能符合要求,
因此实际的i,j, k的起始位置分别为0, 4, 8;
最后由于S的大小位16(4+2+2(填充)+8+4 = 20)不能被大小最大的元素k的
大小8整除,因此需要在l的后面填充4个字节,最终S的大小为24
*/
struct S {
	int i;   // size 4
	short j;   // size 2
	double k;   // size 8
	int l; // size 4
} S1;

2. 有pragma pack的结构体对齐规则

关于pack的详细解释:
see:
https://docs.microsoft.com/en-us/cpp/preprocessor/pack?view=msvc-170

加入了#pragma pack(n)之后规则变成了(这是在一个面经里面看到的,希望有人能指出最原始的出处):

  • 结构体内每一个数据成员的起始位置要是n和当前成员大小中较小值的整数倍
  • 结构体的整体大小要是n和最大变量大小中较小值的整数倍
  • n值必须为1,2,4,8,16,为其他值时就按照默认的分配规则

下面是具体的实例

#include <stddef.h>
#include <stdio.h>
#pragma pack(push)
#pragma pack(2)
struct S {
	int i;   // size 4
	short j;   // size 2
	double k;   // size 8
	int l; // size 4
} S1;
#pragma pack(pop)

int main() {
	// 打印每一个元素的偏移量(也就是起始位置)
	printf("%zu ", offsetof(S, i));
	printf("%zu ", offsetof(S, j));
	printf("%zu ", offsetof(S, k));
	printf("%zu\n", offsetof(S, l));
	printf("S1 size is : %ld\n", sizeof(S1));
}

程序输出结果:
在这里插入图片描述
这是32位平台下运行的结果。

下面是我觉得有用的参考资料:
https://stackoverflow.com/questions/3318410/pragma-pack-effect

https://en.wikipedia.org/wiki/Data_structure_alignment

https://cloud.tencent.com/developer/article/1631792

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值