【Rust中级教程】1.13. 内存中的类型 Pt.1:对齐(Alignment)、布局(Layout)、`repr`属性
1.13 内存中的类型 Pt.1对齐(Alignment)、布局(Layout)、repr属性1.13.1. 类型的基本职责每个Rust值都有类型而类型的职责在于告诉你如何解释内存中的比特位(bits)。例如0b10111101这串比特(bits)本身并没有意义但是- 用u8类型来解释就会得到数字189- 用i8类型来解释就会得到数字-67当自定义类型时编译器决定该类型的各部分在内存表示中的位置1.13.2. 对齐(Alignment)对齐(Alignment)决定了类型的字节可以被存储在哪里。而一旦类型的表示被确定之后你可能想在内存上随便找个地方存进去就行这在理论上是可行的。但实际上计算机硬件对给定的类型可以存放的位置是有约束的。最典型的一个例子是指针它指向的是字节(bytes)而不是位(bits)1个字节等于8比特。换言之它并不指向具体的比特。所以如果将某类型的值放在计算机内存中索引为4的位(bits)上那就无法引用它的地址因为指针指向的是字节而不是具体的比特所以就必须对齐字节也就是对齐到8比特。出于这个原因所有的值无论什么类型都必须开始于字节的边界。所有类型必须至少是字节对齐的(byte-aligned)。换言之存放的地址必须是8bits的整数倍。1.13.3. 更严格的对齐规则有一些类型的对齐规则比字节的对齐规则还要严格在CPU和内存系统里内存经常按大于单个byte的块进行访问。例如在64位的CPU上大部分的值是按照8bytes的块进行访问的每个操作都开始于“8bytes对齐”的地址上。这也叫做CPU的字长英文是word sizeCPU当然也有办法处理更小值的读写以及跨越块边界的值。但是我们作为开发者应该尽可能地保证硬件可以操作于它的原生(native)对齐。举个例子如果想读取的i64值它开始于8bytes块的中间那这个时候要读取它就至少需要两次读取。因为i64是8字节而它开始于两个8字节块中间说明它一定横跨了这两个块。所以在读取时引进就得从这两个块读取数据第一个块读取i64的前面部分第二个块读取i64的后面部分然后再把它们合并到一起。这种操作是非常低效的会拖累程序执行的速度所以我们应该尽可能保证硬件可以操作于它的原生对齐。1.13.4. 没对齐的操作CPU访问内存时数据的地址没有按照架构要求的对齐方式进行访问叫做misaligned access。这会导致性能低下和并发问题。很多CPU操作多要求/强烈建议它们的参数是自然对齐的(naturally aligned)。自然对齐值的对齐是匹配他们值的大小的。例如我想加载8字节那么提供的地址就需要8字节对齐。1.13.5. 编译器会尽可能利用对齐基于类型包含的内容编译器通过计算为类型分配一个对齐或者叫给它分配一个对齐方案- 对于内值的值通常对齐到它们的大小。比如说u8按1字节对齐u16按2字节对齐u32按4字节对齐u64按8字节对齐。而复杂类型包含其它类型的类型通常被赋予所含类型的最大对齐。例如某类型含有u8、u16和u32这三个类型的字段那么类型就应该是4字节对齐u32是最大对齐为4字节1.13.6. 布局(Layout)类型的布局(Layout)指的是编译器决定这个类型在内存上如何表示。Rust编译器对于类型如何布局并没有给出多少保证。Rust提供了repr属性(attribute)它可以添加到你类型的定义上来请求特定的类型表示。1.13.7.repr(C)repr属性(attribute)最常见的一个是repr(C)。名字里带个C说明跟C语言有关系。repr(C)布局方式与C/C编译器对同类型的布局兼容。这对于使用FFI外部函数接口英文是Foreign Function Interface与其它语言交互的Rust代码很有用。使用FFI与其它语言交互的时候Rust会生成一个匹配其它语言编译器期望的布局。因为C语言的布局是可预测且不易改变的所以repr(C)在unsafeunsafe Rust详见 【Rust自学】19.1. 摆脱安全性限制的unsafe Rust的上下文是非常有用的。比如说你使用指向该类型的原始指针时或者在两个具有相同字段的类型间进行转换时都可以使用到repr(C)。1.13.8.repr(transparent)repr(transparent)中的transparent是透明的意思它用于 newtype 风格的包装类型并保证外层类型与其唯一的非零大小字段具有相同的布局。若还有其它字段它们必须是零大小类型例如()或PhantomData。这与newtype模式详见【Rust自学】19.5. 高级类型结合起来很好用。我们在这里回顾一下newtype模式利用元组结构体来构建一个新的类型放在本地相当于是薄封装。举个例子你想操作struct A和struct NewA(A)的内存表示使用了repr(transparent)之后两者的内存表示就应该是一样的。不使用的话Rust编译器就没发保证了。1.13.9. 使用repr属性的例子我们来看一个例子代码字段类型的大小默认内存表示填充最终对齐#[repr(C)]struct Foo {tiny: bool,1 bit1 byte 对齐3 bytesnormal: u32,4 bytes4 bytes 对齐(tinynormal)8 bytessmall: u8,1 byte1 byte 对齐7 bytes8 byteslong: u64,8 bytes8 bytes 对齐8 bytesshort: u16,2 bytes2 bytes 对齐6 bytes8 bytes}共 32 bytes这个表展现了 Rust 结构体在#[repr(C)]下的内存对齐和填充- 代码是最左边的这列使用了repr(C)注解。结构体里面有好几个字段Rust编译器首先看tiny字段是bool类型的占1bit内存就会对齐到1字节编译器接着看normal字段是u32类型的占4字节所以对齐到4字节即可。这时候Rust发现tiny字段对齐到的是1字节所以编译器就会填充3字节让tiny字段占4字节由于这个字段刚好占了8字节是4字节的整数倍所以已经对齐了small字段是u8类型占1字节对齐到1字节。由于上面的两个字段已经对齐了所以Rust编译器会根据下文的字节来判断给它填充多少字节。判断到这里Rust编译器还得观望一下。long是u64类型占8字节自然就是8字节对齐。它的字段是8字节及以上。此时我们看tiny和normal组成了8字节对齐long也是8字节对齐Rust明白了现在的情况是应该按8字节对齐。那就只能给small字段填充7个字节补成一个8字节对齐了。short是u16类型占2字节由于现在的情况是应该按8字节对齐所以编译器会给它补6字节合成8字节对齐。其过程用表格表述就是字段类型大小需要的对齐填充情况备注tiny: bool1 bit1 byte3 bytes 填充为了对齐下一个u32normal: u324 bytes4 bytes无填充按u32对齐small: u81 byte1 byte7 bytes 填充为了对齐下一个u64long: u648 bytes8 bytes无填充8 字节对齐short: u162 bytes2 bytes6 bytes 填充以8字节对齐结构体

相关新闻

【Rust中级教程】1.4. 内存 Pt.2:栈内存、栈帧(stack frame)、栈指针(stack pointer)

【Rust中级教程】1.4. 内存 Pt.2:栈内存、栈帧(stack frame)、栈指针(stack pointer)

1.4 内存 Pt.2:栈内存、栈帧(stack frame)、栈指针(stack pointer) 1.4.1. 内存区域 程序有很多的内存区域,并不都是在DRAM上的。三个比较重要的区域是栈内存stack、堆内存heap和静态内存staic。 栈内存和堆内存相对比,栈内存更快堆内存更…

2026/7/24 20:41:08 阅读更多 →
【Rust中级教程】1.5. 内存 Pt.3:深入探究Rust堆内存底层实现

【Rust中级教程】1.5. 内存 Pt.3:深入探究Rust堆内存底层实现

1.5 内存 Pt.3:深入探究Rust堆内存底层实现 1.5.1. 堆内存(Heap) Heap意味着混乱,而stack则相对比较整齐。Heap是一个内存池,并没有绑定到当前程序的调用栈,而stack绑定到当前程序的调用栈。Heap是为在编译时没有已知大小的类型…

2026/7/24 20:41:08 阅读更多 →
【Rust中级教程】1.6. 内存 Pt.4:静态(static)内存与‘static生命周期标注

【Rust中级教程】1.6. 内存 Pt.4:静态(static)内存与‘static生命周期标注

1.6 内存 Pt.4:静态(static)内存与static生命周期标注 1.6.1. 静态(static)内存 static内存实际上是一个统称,它指的是程序编译后的文件中几个密切相关的区域。当程序执行的时候,这些区域会自动加载到内存里。 static内存里的值会在程序执行期…

2026/7/24 20:41:08 阅读更多 →

最新新闻

从“被生活推动”,进入“主动创造”。

从“被生活推动”,进入“主动创造”。

人生最大的转变,不是环境突然变好了,而是一个人从“反应模式”进入“创造模式”。很多人每天都很忙。 但忙完之后发现: 好像一直在处理事情。 却没有真正建设自己的生活。第一层:什么叫“被生活推动”? 被生活推动的人…

2026/7/24 20:48:09 阅读更多 →
企业全球化新闻发布选哪家?朝闻通海量媒体资源兼顾高效与真实

企业全球化新闻发布选哪家?朝闻通海量媒体资源兼顾高效与真实

时效性是新闻传播的核心内核,也是数字时代衡量品牌传播效率的关键标准。随着信息技术高速迭代,即时发布、快速触达成为新闻公关传播的基本要求。但行业长期存在一大核心矛盾:传播速度与内容精准难以兼顾。一味追求发布速度,极易出…

2026/7/24 20:48:09 阅读更多 →
周报6.21

周报6.21

小组周报小组成员: 陈思潼 汇报周期: 2026年6月17日—2026年6月21日一、本周计划 算法实现与实验验证 可见光与SAR融合目标检测的数据集,可见光与SAR分别使用YOLO系列模型5次重复实验 结果整理与问题分析 汇总实验结果二、本周进展 2.1 实验与…

2026/7/24 20:48:09 阅读更多 →
网络变压器怎么区分单口和双口?

网络变压器怎么区分单口和双口?

网络变压器怎么区分单口和双口? 最快有两招:一看料号里的口数数字,二数线圈图里"1CT:1CT"变压器组数——4 组单口、8 组双口 为什么要先区分单口和双口? 一个 RJ45 网口需要一组网络变压器,对应 4 对差分信…

2026/7/24 20:48:09 阅读更多 →
07.02.03.tiptop集成篇(4gl扩展功能 集成java:封装java的poi包设配4gl 案例 导入excle)

07.02.03.tiptop集成篇(4gl扩展功能 集成java:封装java的poi包设配4gl 案例 导入excle)

本页目录 1、案例2、测试 闲鱼DKLi1717&#xff1a; 引用POI包Excel批量处理 s_poi_excel.4gl 下载excle的模板到桌面anmt200.xlsx 案例 p_test.4fd <?xml version"1.0" encoding"UTF-8" ?> <ManagedForm gstVersion"22800" name…

2026/7/24 20:48:09 阅读更多 →
SDC命令详解:使用set_sense命令进行约束

SDC命令详解:使用set_sense命令进行约束

相关阅读 SDC命令详解https://blog.csdn.net/weixin_45791458/category_12931432.html?spm1001.2014.3001.5482 目录 时钟极性 指定引脚、端口列表/集合 指定类型 指定正单调性 指定负单调性 指定停止传播 指定时钟脉冲 指定时钟列表/集合 指定时钟叶节点 Multicorner-Multim…

2026/7/24 20:47:09 阅读更多 →

日新闻

用Highcharts 创建可拖拽三维散点立方体3D图表

用Highcharts 创建可拖拽三维散点立方体3D图表

该案例基于Highcharts scatter3d 三维散点图实现空间立方体散点可视化&#xff0c;核心特色&#xff1a;三维 X/Y/Z 三轴空间&#xff0c;所有散点分布在 0~10 立方体空间内&#xff1b;散点使用径向渐变实现立体 3D 圆球质感&#xff1b;支持鼠标 / 触屏拖拽画布&#xff0c;…

2026/7/24 0:00:29 阅读更多 →
AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls:进程创建路径上的 DLL 入口

AppCertDlls&#xff1a;进程创建路径上的 DLL 入口 AppCertDlls 位于 HKLM\System\CurrentControlSet\Control\Session Manager\AppCertDlls。本文的程序功能是只读列出这个键在 64 位和 32 位注册表视图中的全部值&#xff0c;并显示每条值的来源、名称、类型和可安全显示的数…

2026/7/24 0:00:29 阅读更多 →
我的编程之路:第一篇博客

我的编程之路:第一篇博客

大家好&#xff0c;我是一名编程初学者&#xff0c;同时这也是我编程学习之路上的第一篇博客。在这里&#xff0c;我想要向大家介绍我的一些想法和规划。a.自我介绍我是一个刚刚接触编程的新手&#xff0c;目前在学习c语言&#xff0c;我对编程世界充满了强烈的好奇。当然&…

2026/7/24 0:00:29 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中&#xff0c;我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源&#xff0c;还是配置文件、证书等&#xff0c;都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下&#xff0c;但这…

2026/7/24 3:59:20 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP&#xff08;轻量级目录访问协议&#xff09;作为企业级身份认证的黄金标准&#xff0c;已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时&#xff0c;发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/24 1:23:39 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”&#xff0c;而是以可解释、可审计、可迭代的方式&#xff0c;赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/24 18:52:18 阅读更多 →

月新闻