C/C++—— 内存字节对齐规则

本文介绍了C/C++中的内存字节对齐规则,包括数据成员对齐、结构体作为成员的对齐以及结构体整体大小的对齐原则。并探讨了#pragma pack(n)指令在内存对齐中的应用,通过实例展示了不同对齐设置对结构体大小的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内存对齐规则:

1.数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储。

比如:

struct s1{
        char a;
        short b;
        double c;
};

该结构体的大小为16个字节。首先a占有1个字节,a从偏移量为0处开始存放。b为short类型,大小为2,所以b从偏移量为2处开始存放。那么偏移量为1处没有存放数据。c大小为8个字节,所以c从偏移量为8处开始存放。所以该结构体占有16个字节。如果c大小为4个字节,所以c从偏移量为4处开始存放。所以该结构体占有8个字节。

2.结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct s2里存有struct s1,s1里有char,int ,double等元素,那s1应该从8的整数倍开始存储.)

struct s1{
        char a;
        short b;
        double c;
};

struct s2{
        char d;
        struct s1 s11;
};

结构体s1占用16个字节空间。s1中最大元素的大小为8个字节,所有该结构体应该从8个整数倍地址开始存储,前面只有一个字节的d变量。所有s1结构体应该从偏移量为8处开始存放。所以该结构体占有8+16=24个字节。<

### 关于 `offsetof` 宏和字节对齐 #### `offsetof` 宏的功能描述 `offsetof()` 宏用于计算结构体成员相对于结构体起始位置的偏移量。其原型为 `offsetof(type, member)`,其中 `type` 是结构体类型而 `member` 则是该结构体内的某个成员名称[^1]。 ```cpp #include <stddef.h> struct Example { int a; char b; }; size_t offset_b = offsetof(struct Example, b); printf("Offset of 'b' is %zu bytes.\n", offset_b); ``` 这段代码展示了如何利用 `offsetof` 来获取名为 `Example` 的结构体中字段 `b` 对应的偏移量并打印出来。 #### 字节对齐原则及其影响因素 当涉及到内存布局时,编译器通常会对数据项按照特定规则进行排列以优化访问效率——这就是所谓的“字节对齐”。具体来说: - **基本单位**:不同平台上的处理器有不同的自然边界长度(如32位机器上通常是4个字节),这决定了最小存储单元大小; - **填充机制**:为了使下一个元素能够放置在其最合适的地址处,可能会在两个连续的数据之间插入额外的空间作为填充; - **对齐方式**:取决于目标架构以及编程语言本身的规定;对于C/C++而言,默认情况下会遵循一定的模式来安排各组成部分的位置关系[^5]。 考虑如下例子: ```cpp struct AlignedStruct { char ch; // 1 byte short sh; // 2 bytes (will be padded to align with next boundary) int nInts[2]; // each element takes up 4 bytes }; ``` 在这个案例里,尽管字符型变量只需要占用单个字节空间,但由于后续存在更宽泛类型的短整数 (`short`) 需要两字节对齐,因此会在两者间加入适当数量的空白区域确保后者能被正确定位到偶数地址上去。 #### 结合实例说明 下面通过具体的程序片段进一步解释上述概念的应用场景: ```cpp #include <stdio.h> #include <stddef.h> struct MyStruct { char c; /* 占用1字节 */ int i; /* 占用4字节,在某些平台上可能需要前置填充至4字节边界 */ double d; /* 占用8字节,同样需满足相应的对齐需求 */ }; int main(void){ printf("Sizeof(MyStruct):%lu\n", sizeof(struct MyStruct)); size_t off_c = offsetof(struct MyStruct, c); size_t off_i = offsetof(struct MyStruct, i); size_t off_d = offsetof(struct MyStruct, d); printf("Offset of 'c': %zu\n", off_c); printf("Offset of 'i': %zu\n", off_i); printf("Offset of 'd': %zu\n", off_d); return 0; } ``` 此段代码不仅体现了 `offsetof` 函数的作用还揭示了由于字节对齐所引起的实际尺寸变化情况。注意这里输出的结果将依赖于运行环境的具体实现细节,比如操作系统版本、硬件体系结构等因素都会有所差异[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值