结构体的内存对齐与位段的结构体实现
求结构体总大小(字节数)的规则
- 结构体第一个成员在结构体变量偏移量从0开始地址数
- 结构体其余成员对齐数的整数倍的地址数
- 对齐数:默认的对齐数与结构体成员大小的较小值
- vs的对齐数为8 / linux没有对齐数概念
- 结构体总大小(字节数)为最大对齐数(结构体成员的字节数)的整数倍
- 结构体嵌套的对齐数为整个结构体最大的对齐数的整数倍的地址,结构体总大小为所有对齐数的整数倍
为什么存在内存对齐
1.(平台/移植)原因:让数据只存在可以被访问的地址上,不会抛出异常,不是 所有 硬件可以 访问任意地址的数据,只能访问某些地址处取某些特定类型数据,否则抛出异常
2.(性能)原因:数据结构(尤其是栈)尽可能在自然边界上对齐,访问未对齐的内存,这需要两 次读取,对齐的内存,则仅需要读取一次(每次访问4个字节)
建议:让占用空间小的成员尽量放在一起,节省空间
修改对齐数:
- #pragma pack(2) 有参则设置默认对齐数 无则取消设置的默认对齐数
- pack(1) 没有偏移 顺着放
- 建议:如果结构体对齐方式不合适的话,可以自己进行手动修改默认对齐数
- offsetof (头文件 stddef.h)
- 计算结构体的某变量相对于首地址的偏移量
- offsetof(结构体类型,结构体内的某变量
结构体传参(传值和传址)
1.结构体传值,形参时实参的一个拷贝,函数调用一次,内存会每调一次开辟与结构体变量 一样大的空间
(参数在内存中是压栈,时间和空间的开销,系统开销大)
2.结构体传址,不会内存开辟,但是会改变结构体变量的值
结构体实现位段
位段的存在原因:为你所需分配足够的内存空间
位段成员必须是整形家族(常见是int,unsigned int,signed int )
//结构体实现位段 struct A { int _a : 2; // 后面的数字代表占几个bit位 int _b : 3; int _c : 4; };
//结构体实现位段
//书写方式 类型 变量名 : 数值
struct A
{
int _a : 2; // 后面的数字代表占几个bit位
int _b : 3;
int _c : 4;
};
位段的内存分配
位段的空间上是按照需要4个字节int或一个字节char的方式开辟
一个字节先用低地址
在用高地址 剩下的成员不够用会浪费
位段的不确定因素,微端不确定不跨平台,注重可移植性的避免使用位段
位段的跨平台性
1.int位段被当做int还是unsigned来处理
2.位段中的成员在内存中是从左到右,还是从右到左分配
3.位段中最大的数目不确定(不同机器位数不一样,小的位数机器,你写的超过了最大位数, 会出错)
4.当一个结构包含两个位段,第二个位段成员较大,无法容纳第一个位段成员剩余的位数, 剩余的位数是舍弃还是利用,不确定
注意:与结构体相比,位段可以达到同样效果,可以更好节省空间,但是平台可移植性还是存在
网络数据包发送,你需要多大空间,给多大空间,能够节省空间,不会过多浪费
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」