【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/8/9 15:30:31 阅读更多 →
【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/8/14 11:39:20 阅读更多 →
【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/8/15 19:54:59 阅读更多 →

最新新闻

nslookup命令使用说明

nslookup命令使用说明

个人建站,域名备案完成后,往往还要做域名解析服务,技术人员怎么能知道自己配置的DNS正确与否呢?NSLOOKUP查询域名信息的一个非常有用的命令,可以指定查询的类型,可以查到DNS记录的生存时间还可以指定使用哪…

2026/8/17 0:00:08 阅读更多 →
【原创唯一】基于SpringBoot+Vue的在线书店商城系统 课程设计/大作业/期末作业(源码+MySQL数据库+实验报告+PPT+远程部署)

【原创唯一】基于SpringBoot+Vue的在线书店商城系统 课程设计/大作业/期末作业(源码+MySQL数据库+实验报告+PPT+远程部署)

摘要 电子商务与移动支付的普及,线上购书已成为高校师生及社会公众获取图书的重要方式。传统线下书店在图书检索、库存查询、订单跟踪等方面存在信息分散、效率较低等问题。本文设计并实现了一套基于 B/S 架构的网上书店系统,采用前后端分离模式&#xf…

2026/8/17 0:00:08 阅读更多 →
飞书局域网文件传输实战:3种方案实现高速点对点传输

飞书局域网文件传输实战:3种方案实现高速点对点传输

1. 项目概述:为什么要在局域网内用飞书传文件? 飞书作为一款主流的协同办公套件,其核心功能是围绕云端协作设计的。无论是文档、表格还是文件,通常的分享逻辑都是“上传到云端 -> 生成链接 -> 分享给同事”。这个流程在互联…

2026/8/17 0:00:08 阅读更多 →
LabVIEW异步调用实战:解决界面卡顿与并行处理难题

LabVIEW异步调用实战:解决界面卡顿与并行处理难题

1. 项目概述:为什么异步调用是LabVIEW进阶的必经之路如果你在LabVIEW里写过稍微复杂点的程序,尤其是涉及到界面响应、多任务并行或者硬件IO等待,大概率会遇到一个头疼的问题:程序“卡”住了。前面板点不动,进度条不更新…

2026/8/17 0:00:08 阅读更多 →
LabVIEW异步调用实战:从原理到生产者消费者模式,解决界面卡顿与并行处理难题

LabVIEW异步调用实战:从原理到生产者消费者模式,解决界面卡顿与并行处理难题

1. 项目概述:为什么异步调用是LabVIEW进阶的必修课? 如果你用LabVIEW做过稍微复杂点的项目,尤其是涉及界面响应、多任务并行或者硬件IO等待的场景,大概率遇到过这样的窘境:前面板点个按钮,整个程序就“卡死…

2026/8/17 0:00:08 阅读更多 →
错误分享:误将磁盘分区类型选成磁盘名称

错误分享:误将磁盘分区类型选成磁盘名称

1.先删除原有分区2.fdisk重新创建3.发现进程被占用4.使用kill关不掉进程,加 -9 强制关闭5.关闭后重新使用fdisk创建,tips:记得改完后要使用 w 保存

2026/8/16 23:59:08 阅读更多 →

日新闻

LabVIEW异步调用实战:从原理到生产者消费者模式,解决界面卡顿与并行处理难题

LabVIEW异步调用实战:从原理到生产者消费者模式,解决界面卡顿与并行处理难题

1. 项目概述:为什么异步调用是LabVIEW进阶的必修课? 如果你用LabVIEW做过稍微复杂点的项目,尤其是涉及界面响应、多任务并行或者硬件IO等待的场景,大概率遇到过这样的窘境:前面板点个按钮,整个程序就“卡死…

2026/8/17 0:00:08 阅读更多 →
LabVIEW异步调用实战:解决界面卡顿与并行处理难题

LabVIEW异步调用实战:解决界面卡顿与并行处理难题

1. 项目概述:为什么异步调用是LabVIEW进阶的必经之路如果你在LabVIEW里写过稍微复杂点的程序,尤其是涉及到界面响应、多任务并行或者硬件IO等待,大概率会遇到一个头疼的问题:程序“卡”住了。前面板点不动,进度条不更新…

2026/8/17 0:00:08 阅读更多 →
飞书局域网文件传输实战:3种方案实现高速点对点传输

飞书局域网文件传输实战:3种方案实现高速点对点传输

1. 项目概述:为什么要在局域网内用飞书传文件? 飞书作为一款主流的协同办公套件,其核心功能是围绕云端协作设计的。无论是文档、表格还是文件,通常的分享逻辑都是“上传到云端 -> 生成链接 -> 分享给同事”。这个流程在互联…

2026/8/17 0:00:08 阅读更多 →

周新闻

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

基于阿里云与通义千问(Qwen)构建AI应用:从模型调用到生产部署的完整实践指南

如果你是一名开发者,最近可能已经感受到了AI大模型正在从“玩具”变成“生产力工具”的强烈信号。从代码补全到智能Agent,从本地部署到云端API,我们正处在一个技术栈快速重构的节点。然而,面对层出不穷的模型、框架和工具&#xf…

2026/8/16 0:00:54 阅读更多 →
工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

工业通信系统底层逻辑:04 反射——高频能量撞墙之后会发生什么?

第四篇:反射——高频能量撞墙之后会发生什么? —— 你以为信号已经过去了,其实它正在回来打你 老Q的现场笔记 第五季,我们正式进入工业神经系统层。这里不再是单个设备的战斗,而是整个工厂“经脉”层面的秩序之战。从这一篇开始,你将第一次看清:看似简单的信号传播,背…

2026/8/16 0:00:55 阅读更多 →
【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

【文章复现】非线性值迭代自适应动态规划(ADP):离散时间非线性系统的策略迭代自适应动态规划算法研究附Matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。🍎 往期回顾关注个人主页:Matlab科研工作室👇 关注我领取海量matlab电子书和…

2026/8/16 0:03:55 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/16 6:00:23 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/16 6:00:24 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/16 6:00:27 阅读更多 →