内存对齐——#pragma pack()用法

本文介绍了C/C++编译器的缺省字节对齐规则,特别是#pragmapack指令如何改变内存对齐,通过一个struct示例展示了如何使用pragmapack(1)来调整结构体的对齐方式。

        C/C++编译器的缺省字节对齐方式为自然对界。即在缺省情况下,编译器为每一个变量或是数据单元按其自然对界条件分配空间。编译器缺省的结构成员自然对界条件为“N字节对齐”,N即该成员数据类型的长度。如int型成员的自然对界条件为4字节对齐,而double类型的结构成员的自然对界条件为8字节对齐。若该成员的起始偏移不位于该成员的“默认自然对界条件”上,则在前一个节面后面添加适当个数的空字节。

1.#pragma简述

        预处理指令,设定编译器的状态或者指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。

2.#pragma pack()的作用

   #pragma pack 的主要作用就是改变编译器的内存对齐方式,这个指令在网络报文的处理中有着重要的作用,#pragma pack(n)是他最基本的用法,其作用是改变编译器的对齐方式, 不使用这条指令的情况下,编译器默认采取#pragma pack(8)也就是8字节的默认对齐方式,n值可以取(124816) 中任意一值。

#include <stdio.h>
#include <stdint.h>


#pragma pack (1)
struct Test {
    uint32_t var1:24;
    uint32_t var2:8;
    uint16_t year;
    uint8_t moth[3];
};
#pragma pack ()

int main(void)
{
    Test var = {1, 2, 3,4,5,6};

    printf("sizeof(Test) = %lld\n", sizeof(Test));
    printf("%d %d %d %d %d %d\n", var.var1, var.var2, var.year,var.moth[1],var.moth[2],var.moth[0]);
    return 0;
}

运行结果:

 

### 内存对齐的概念 内存对齐是指将数据存储在内存中时,按照特定规则进行字节对齐的过程。这样做可以提高程序执行效率,因为某些硬件架构对于未对齐的数据访问速度较慢甚至无法正常工作[^1]。 ### 实现方式 #### 编译器自动调整 编译器通常会在后台自动完成大部分必要的内存对齐操作。当程序员声明结构体或其他复合类型时,编译器会根据目标平台的要求,在各字段间插入填充字节以确保整个对象能够正确地按边界排列。 #### 使用预处理器指令控制对齐行为 可以通过`#pragma pack(n)`来改变默认的打包规则,其中n表示所期望的最大对齐单位大小(如1, 2, 4, 8)。此命令会影响随后定义的所有结构直到遇到另一个相同形式的语句为止[^2]。 ```cpp #pragma pack(push, 1) // 设置当前文件内的后续结构体为一字节对齐 struct Example { char a; /* offset=0 */ short b; /* offset=1 (no padding added before this member) */ }; #pragma pack(pop) // 恢复之前的对齐设置 ``` #### 利用C++11特性指定对齐属性 自C++11起提供了两个关键字——`alignas` 和 `alignof` 来显式设定或查询类型的最小允许对界值。前者可用于强制某个实体遵循给定的对齐约束;后者则返回其参数的实际对齐程度[^4]。 ```cpp // 定义一个至少四字节对齐的新类型 using AlignedType = alignas(4) int; static_assert(sizeof(int) % alignof(AlignedType) == 0, "The size of the type must be multiple of its alignment."); ``` ### 计算成员偏移量的方法 要计算结构体内各个元素相对基址的位置,需考虑每项自身的尺寸及其所属类别的自然对齐需求。具体而言: - 对于基本数据类型,取它们各自占用的空间数作为依据; - 复杂类型应参照内部最严格条件者为准; - 结构结束处还可能存在额外空白区以便整体满足最低限度要求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值