活动介绍

Rust编程:变量、数据类型与常见应用场景

立即解锁
发布时间: 2025-09-04 01:49:30 阅读量: 2 订阅数: 17 AIGC
PDF

Rust新手入门实战指南

### Rust编程:变量、数据类型与常见应用场景 #### 1. 理解Rust中的变量声明与使用 在Rust里,变量声明采用`let`关键字,它能在标识符和值之间建立绑定关系。默认情况下,这些绑定是不可变的,也就是说,一旦给变量赋值,就无法再更改它。例如: ```rust let x = 42; ``` 在这个例子中,变量`x`被绑定到值`42`,并且在其作用域内始终保持不变。若程序员在后续代码中尝试修改`x`,编译器会报错。这种默认的不可变性是Rust的核心概念,它能强制实施安全的编程规范,避免意外的副作用。 Rust的编译器会利用类型推断,依据赋给变量的值来推断其类型。比如,用整数字面量初始化变量时,除非另有指定,编译器会将类型推断为`i32`。这减轻了程序员在每个实例中都显式声明类型的负担,同时仍能保证严格的类型安全。不过,若有需要或为了明确预期用途,程序员也可以显式标注变量类型,例如: ```rust let y: u32 = 100; ``` 这种显式标注在默认类型推断可能导致歧义,或者与外部系统交互时类型必须精确的情况下很有用。 若程序员希望在变量初始声明后允许对其进行修改,可使用`mut`关键字。给变量绑定加上`mut`前缀后,变量就变为可变的,其值可以被更改。示例如下: ```rust let mut counter = 0; counter = counter + 1; ``` 这里,变量`counter`初始值为`0`,随后被加`1`。不过,使用可变变量时需谨慎,因为若管理不当,启用可变性可能会引发错误。 Rust中的变量还可以在不赋初始值的情况下声明,但此时必须进行类型标注,因为编译器在没有初始值时无法推断类型。例如: ```rust let result: i32; result = 10 + 32; ``` 这种声明方式常用于声明时初始值未知的情况,比如从输入源读取数据时。 Rust支持变量声明中的解构操作,可从复合数据结构中同时声明并赋值多个变量。以元组为例: ```rust let tuple = (500, 6.4, 1); let (x, y, z) = tuple; ``` 在这个例子中,元组包含三个不同类型的元素,后续声明通过模式匹配将元组解包为单独的变量`x`、`y`和`z`,这样能使代码更易读和维护。 Rust严格执行变量作用域规则,变量的生命周期仅限于其声明所在的代码块。代码块由花括号`{...}`定义,在块内声明的变量仅在该块内可访问,块退出时会自动释放。例如: ```rust { let a = 10; // 变量 ’a’ 在这个块内可访问 println!("Value of a: {}", a); } // 块外,’a’ 不再可访问。 ``` 这种严格的作用域管理有助于防止悬空引用或意外的内存保留问题。 当在程序中声明或使用变量时,Rust的编译器会检查是否遵守所有权和借用规则,这是Rust保证内存安全和并发安全而无需垃圾回收器的关键。例如,当函数获取传递给它的变量的所有权时,该变量在调用作用域中会失效,除非它实现了`Copy`特征,此时会隐式复制。 在Rust中声明变量时,常结合使用`println!`宏来打印或记录信息以进行调试。例如: ```rust let name = "Rust Developer"; println!("Hello, {}", name); ``` 此代码片段中,变量`name`存储一个字符串切片,并被插入到输出消息中,结果会显示在控制台。 下面是Rust变量声明的相关要点总结表格: | 特性 | 描述 | 示例 | | ---- | ---- | ---- | | 默认不可变 | 变量绑定默认不可变,防止意外修改 | `let x = 42;` | | 类型推断 | 编译器根据赋值推断变量类型 | `let x = 42; // 推断为i32` | | 显式类型标注 | 明确指定变量类型 | `let y: u32 = 100;` | | 可变变量 | 使用`mut`关键字使变量可变 | `let mut counter = 0; counter = counter + 1;` | | 无初始值声明 | 声明时无初始值需类型标注 | `let result: i32; result = 10 + 32;` | | 解构操作 | 从复合数据结构中同时声明多个变量 | `let tuple = (500, 6.4, 1); let (x, y, z) = tuple;` | | 作用域规则 | 变量生命周期限于声明所在块 | `{ let a = 10; println!("Value of a: {}", a); }` | #### 2. Rust变量的可变性 在Rust中,可变变量和不可变变量的区别是语言设计的基本方面,它提供了一个框架,在需要修改状态时允许有控制的灵活性,同时促进代码的安全性和可预测性。默认情况下,Rust中的变量是不可变的,这意味着一旦一个值被绑定到一个变量,任何试图改变该值的操作都会导致编译时错误。这种行为是为了防止意外的副作用,并便于对程序状态进行推理。不可变变量是Rust对安全性承诺的核心,特别是在多线程环境中,可变的共享状态可能会导致数据竞争或其他并发问题。 要明确允许修改变量,Rust要求在声明中包含`mut`关键字。添加`mut`表示程序员打算让变量的状态随时间改变。例如: ```rust let mut count = 0; count = count + 1; ``` 在这个代码片段中,变量`count`首先被声明并初始化为`0`。使用`mut`允许后续的操作将其值增加`1`。如果没有`mut`修饰符,代码将无法编译,这为意外的重新赋值提供了直接的保护。这种行为凸显了Rust中不可变性的一个主要原因:默认情况下,编译器强制执行可预测的程序流程,最大限度地减少状态变化。 优先选择不可变性的理由不仅仅局限于简单的变量赋值。不可变数据使程序行为更容易推理:对不可变数据进行操作的函数不会产生可能影响程序其他部分的副作用。想象一下,多个线程同时访问一个变量的场景;如果该变量是可变的,程序员将不得不实现额外的同步机制来防止数据竞争。以不可变性为默认设置,Rust从根本上降低了并发修改导致不可预测行为的风险。 相反,可变变量在预期值会发生变化的情况下是不可或缺的,比如循环中的计数器、聚合中的累加器,或者存储来自用户输入或传感器读数的动态状态的变量。然而,应该谨慎使用它们。Rust的设计理念是除非绝对必要,否则不鼓励使用可变性。通过明确表示可变性,该语言迫使程序员验证状态变化是有意为之,并考虑状态修改的潜在影响。 除了局部变量的修改,Rust的可变性模型还与所有权和借用相互作用。当将可变变量传递给函数时,函数必须明确声明它期望一个可变引用。这通过在函数参数中使用`&mut`表示法来实现。考虑以下示例,它定义了一个函数来增加对整数的可变引用: ```rust fn increment(value: &mut i32) { *value += 1; } fn main() { let mut num = 10; increment(&mut num); println!("num: {}", num); } ``` 在上面的示例中,`increment`函数接收一个对整数的可变引用。它解引用指针,修改底层数据,然后退出。`main`函数中的变量`num`是可变的,允许传递可变引用。强制的语法和语义确保声明需要可变引用的函数可以安全地这样做,并且任何试图通过不可变引用修改变量的尝试都将在编译时被捕获。 Rust中可变性的一个重要方面是,可变性适用于绑定,而不一定适用于被引用的值。换句话说,将变量声明为可变意味着绑定本身可以被重新赋值,但复杂数据类型(如向量或结构体)中的元素可能仍然是不可变的,除非它们被明确声明为可变。这种行为确保了变量的绑定(指示值的存储位置)和值本身的内容之间保持清晰的区别。 考虑一个可变向量的情况。虽然向量变量被声明为可变的,但只有当元素的类型允许内部修改时,单个元素才可能是可变的。以下示例说明了这种细微差别: ```rust let mut numbers = vec![1, 2, 3]; numbers.push(4); numbers[0] = 10; ``` 在这段代码中,向量`numbers`是可变的,允许进行诸如`push`和元素重新赋值的操作。向量本身的可变性允许动态修改其大小和内容。然而,Rust的安全保证确保即使存在对向量的多个引用,可变借用规则也能防止可能导致数据竞争的并发修改。 Rust的可变性规则也适用于像结构体这样的复杂数据结构。可以将结构体声明为可变的,以便可以更新各个字段。当数据结构表示随时间演变的状态时,这特别有用,例如游戏中的实体,其位置或健康状况会随时间变化。可变结构体的声明如下所示: ```rust struct Player { name: String, score: i32, } fn main() { let mut player = Player { name: String::from("Alice"), score: 0 }; player.score += 10; println!("Player {} has a score of {}", player.name, player.score); } ``` 在这里,只有绑定`player`被标记为可变,允许修改其字段。如果结构体没有使用`mut`声明,编译器将禁止任何修改,从而确保开发者在需要可变状态时做出明确的决定。 可变变量和不可变变量之间的选择不仅仅是语法上的,也是语义上的。在数据是常量的情况下,如配置参数或程序开始时计算的值,首选不可变变量,而可变变量则用于值本质上是动态的情况。这种区别在确保代码易于理解、最小化意外副作用以及减少因意外状态变化而可能出现的错误方面起着关键作用。 此外,Rust默认严格执行不可变性对程序优化有影响。当编译器能够保证变量不会改变时,通常会进行更激进的优化。不可变数据允许编译器进行精确的分析和优化,如常量折叠或内联,从而生成高效的可执行代码。在需要使用可变变量的情况下,程序员必须明确平衡灵活性的需求和性能考虑。 对于初学者来说,在学习Rust时,最初专注于不可变变量是有益的。强调不可变性鼓励开发更易于调试和维护的代码。在掌握了不可变变量的示例后,可以根据需要逐步引入可变状态,始终权衡代码清晰度和状态变化必要性之间的取舍。随着时间的推移,程序员会欣赏Rust默认不可变模型所强制执行的规范,这将导致设计出健壮可靠的软件系统。 下面是一个简单的mermaid流程图,展示了Rust中变量可变性的决策过程: ```mermaid graph TD; A[是否需要修改变量值?] -->|是| B[使用mut声明可变变量]; A -->|否| C[使用默认不可变声明]; B --> D[传递可变引用时函数需声明&mut]; C --> E[函数可接收不可变引用]; ``` 可变变量在涉及状态管理的设计模式中也有影响。例如,有限状态机或跟踪迭代进度的计数器自然需要可变变量。在这种情况下,使用`mut`是不可避免的。然而,即使需要可变状态,Rust的借用检查器也确保同一时间只有一个可变引用存在,或者有多个不可变引用,这保证了状态被安全地访问。这种访问控制的二分法是Rust设计中的关键创新之一。 编译器关于可变性的严格规则甚至延伸到闭包。当闭包从其环境中捕获变量时,它可以通过引用进行捕获。如果闭包打算修改其捕获的状态,则必须将其声明为可变的。省略此声明会导致编译时错误,因为Rust要求程序员在允许进行可变操作时明确表明意图。这种模式确保闭包捕获的状态得到清晰管理,并防止不安全的并发修改。 开发者还应该注意,Rust中的可变变量与遮蔽(shadowing)的概念相互作用。遮蔽允许声明一个与先前变量同名的新变量,实际上在新的作用域中“隐藏”了原始绑定。即使原始变量是不可变的,也允许进行遮蔽,并且新绑定可能具有不同的类型。这种机制与可变性不同,它是一种转换数据的工具。虽然可变变量支持显式的状态更改,但遮蔽提供了一种在不借用原始变量可变性的情况下以受控方式更新变量值的方法。这种模式在分阶段处理数据时特别强大,每个新绑定都反映了对先前数据的转换。 Rust中对可变性的明确和审慎处理证明了该语言通过清晰性来强调安全性。每个可变变量都伴随着跟踪其状态变化的责任。编译器的检查作为即时反馈机制,确保在开发过程的早期捕获潜在错误。这种严格的方法营造了一个优先考虑代码正确性的开发环境,并防止任何偏离预期状态修改的情况发生。 #### 3. Rust程序的编译与运行 在Rust中,编译和运行程序并非一次性的任务,而是一个迭代的循环,这构成了开发的核心。代码、编译器反馈和运行时执行之间的紧密集成,使开发者能够快速识别问题并验证更改。全面的错误消息,加上对安全性和正确性的强调,确保这个循环能有效地支持小型实用程序和大型复杂应用程序的开发。 开发者可以通过`rustc`直接编译,也可以使用功能更丰富的`Cargo`工作流,选择最适合当前需求的方法。`Cargo`的额外功能,如管理依赖项、强制执行编码标准、自动化测试和编排构建工件,为Rust高效可靠的软件开发奠定了坚实的基础。 下面是使用`rustc`和`Cargo`编译运行Rust程序的步骤: - **使用`rustc`编译运行**: 1. 编写Rust代码,保存为`.rs`文件,例如`main.rs`。 2. 打开终端,进入代码所在目录。 3. 执行命令`rustc main.rs`,编译器会生成一个可执行文件(在Windows上是`.exe`文件,在Linux和macOS上是无扩展名的可执行文件)。 4. 运行生成的可执行文件,如在Linux和macOS上执行`./main`,在Windows上执行`main.exe`。 - **使用`Cargo`编译运行**: 1. 创建新的Cargo项目,执行命令`cargo new my_project --bin`,`--bin`表示创建一个可执行程序项目。 2. 进入项目目录`cd my_project`。 3. 在`src/main.rs`中编写Rust代码。 4. 编译项目,执行`cargo build`,编译结果会存放在`target/debug`目录下。 5. 运行项目,执行`cargo run`,Cargo会自动编译并运行程序。 以下是一个简单的mermaid流程图,展示了使用`Cargo`开发Rust程序的基本流程: ```mermaid graph LR; A[创建Cargo项目] --> B[编写代码]; B --> C[编译项目:cargo build]; C --> D[运行项目:cargo run]; D --> E{是否有问题?}; E -->|是| B; E -->|否| F[发布项目:cargo publish]; ``` #### 4. Rust的常见应用场景 Rust是一种通用的编程语言,专注于安全性、性能和并发性。其设计优先级使其特别适合各种对可靠性和效率要求极高的应用场景。以下是Rust在不同领域的应用介绍: | 应用领域 | 优势 | 示例 | | ---- | ---- | ---- | | 系统编程 | 通过所有权、借用和生命周期规则进行严格的编译时检查,保证内存安全,无垃圾回收的运行时开销 | 操作系统、设备驱动、嵌入式软件 | | 并发编程 | 类型系统和并发模型确保在编译时捕获数据竞争,可控制地使用多线程 | 高性能并发服务器、并行处理系统、实时数据分析工具 | | 网络应用 | 强大的安全保证防止安全漏洞,支持异步编程 | 网络服务器、客户端、分布式系统 | | 游戏开发 | 零成本抽象允许构建高级结构而无额外运行时开销,可精确控制内存和处理资源 | 游戏引擎、实时模拟、物理引擎 | | 命令行应用 | 利用错误处理和类型安全,生成快速执行、内存占用少的程序,`Cargo`简化依赖管理和构建过程 | 文件处理工具、系统监控工具、数据转换工具 | | 网页开发 | 通过WebAssembly(Wasm)在浏览器中以接近原生的速度运行,高效的内存管理和编译时保证 | 视频处理、虚拟现实、实时游戏等Web应用 | | 嵌入式系统 | 生成高效的机器级代码,结合严格的安全检查,适用于资源受限环境 | 工业自动化、消费电子、物联网设备 | | 大型代码库开发 | 模块系统和严格的编译时接口执行,便于维护和扩展 | 分布式系统、数据库、实时分析平台 | | 高安全应用 | 编译时检查消除常见错误,降低安全漏洞风险 | 金融、医疗、关键基础设施领域的软件 | 下面详细介绍几个常见应用场景: - **系统编程**:历史上,C和C++等语言在系统编程领域占据主导地位,因为它们能够生成高度优化的机器代码,并提供对硬件资源的低级控制。然而,这些语言缺乏固有的安全特性,可能导致缓冲区溢出、空指针解引用和多线程环境中的数据竞争等常见错误。Rust通过其所有权、借用和生命周期规则进行严格的编译时检查,解决了这些问题。这些特性保证了内存安全,而不会产生与垃圾回收相关的运行时开销。因此,Rust在开发操作系统、设备驱动和嵌入式软件方面特别有效,因为这些场景对性能和可靠性要求极高。 - **并发编程**:在需要多个进程或线程同时运行的应用程序中,竞态条件和死锁等问题可能严重影响软件质量。Rust的类型系统和并发模型确保在编译时捕获数据竞争,而不是在执行期间。该语言能够强制执行不可变状态和安全的可变访问,使开发者能够以受控的方式使用多线程。这使得Rust成为开发高性能并发服务器、并行处理系统和实时数据分析工具的有力候选者。Rust提供的编译时保证减少了通常在支持并发编程但不严格执行的语言中所需的调试和运行时错误处理工作量。 - **网络应用**:构建网络服务器、客户端和其他分布式系统需要强大的健壮性和处理高并发的能力。Rust强大的安全保证可防止导致安全漏洞的各种漏洞,如使用后释放错误和内存损坏问题。此外,Rust通过利用其并发模型的框架为异步编程提供了出色的支持。这种能力使开发者能够编写既响应迅速又能有效处理大量并发连接的网络应用程序。设计Web服务器、网络代理或协议的开发者可以从这些性能提升中受益,同时确保代码的安全性和可维护性。 - **游戏开发**:Rust对零成本抽象的强调吸引了开发者,特别是在对性能要求极高的游戏开发领域。零成本抽象允许构建高级结构而不产生额外的运行时开销。在游戏开发中,性能至关重要,而开发系统的复杂性又需要清晰的抽象。使用Rust构建的游戏引擎、实时模拟和物理引擎可以实现高帧率和响应性,同时严格控制内存和处理资源。与通过动态类型维护高级抽象或在引入抽象时遭受性能损失的语言相比,Rust提供了可预测的性能,通常通过编译时检查来验证。 Rust凭借其独特的特性,在多个领域展现出强大的优势。无论是对安全性要求极高的系统编程,还是对性能和并发性有严格要求的网络和游戏开发,Rust都能提供可靠的解决方案。随着开发者对Rust的深入了解和应用,它将在现代软件工程中发挥越来越重要的作用。
corwn 最低0.47元/天 解锁专栏
赠100次下载
点击查看下一篇
profit 400次 会员资源下载次数
profit 300万+ 优质博客文章
profit 1000万+ 优质下载资源
profit 1000万+ 优质文库回答
复制全文

相关推荐

李_涛

知名公司架构师
拥有多年在大型科技公司的工作经验,曾在多个大厂担任技术主管和架构师一职。擅长设计和开发高效稳定的后端系统,熟练掌握多种后端开发语言和框架,包括Java、Python、Spring、Django等。精通关系型数据库和NoSQL数据库的设计和优化,能够有效地处理海量数据和复杂查询。
最低0.47元/天 解锁专栏
赠100次下载
百万级 高质量VIP文章无限畅学
千万级 优质资源任意下载
千万级 优质文库回答免费看

最新推荐

Rust开发实战:从命令行到Web应用

# Rust开发实战:从命令行到Web应用 ## 1. Rust在Android开发中的应用 ### 1.1 Fuzz配置与示例 Fuzz配置可用于在模糊测试基础设施上运行目标,其属性与cc_fuzz的fuzz_config相同。以下是一个简单的fuzzer示例: ```rust fuzz_config: { fuzz_on_haiku_device: true, fuzz_on_haiku_host: false, } fuzz_target!(|data: &[u8]| { if data.len() == 4 { panic!("panic s

iOS开发中的面部识别与机器学习应用

### iOS开发中的面部识别与机器学习应用 #### 1. 面部识别技术概述 随着科技的发展,如今许多专业摄影师甚至会使用iPhone的相机进行拍摄,而iPad的所有当前型号也都配备了相机。在这样的背景下,了解如何在iOS设备中使用相机以及相关的图像处理技术变得尤为重要,其中面部识别技术就是一个很有价值的应用。 苹果提供了许多框架,Vision框架就是其中之一,它可以识别图片中的物体,如人脸。面部识别技术不仅可以识别图片中人脸的数量,还能在人脸周围绘制矩形,精确显示人脸在图片中的位置。虽然面部识别并非完美,但它足以让应用增加额外的功能,且开发者无需编写大量额外的代码。 #### 2.

React应用性能优化与测试指南

### React 应用性能优化与测试指南 #### 应用性能优化 在开发 React 应用时,优化性能是提升用户体验的关键。以下是一些有效的性能优化方法: ##### Webpack 配置优化 通过合理的 Webpack 配置,可以得到优化后的打包文件。示例配置如下: ```javascript { // 其他配置... plugins: [ new webpack.DefinePlugin({ 'process.env': { NODE_ENV: JSON.stringify('production') } }) ],

Rust模块系统与JSON解析:提升代码组织与性能

### Rust 模块系统与 JSON 解析:提升代码组织与性能 #### 1. Rust 模块系统基础 在 Rust 编程中,模块系统是组织代码的重要工具。使用 `mod` 关键字可以将代码分隔成具有特定用途的逻辑模块。有两种方式来定义模块: - `mod your_mod_name { contents; }`:将模块内容写在同一个文件中。 - `mod your_mod_name;`:将模块内容写在 `your_mod_name.rs` 文件里。 若要在模块间使用某些项,必须使用 `pub` 关键字将其设为公共项。模块可以无限嵌套,访问模块内的项可使用相对路径和绝对路径。相对路径相对

AWS无服务器服务深度解析与实操指南

### AWS 无服务器服务深度解析与实操指南 在当今的云计算领域,AWS(Amazon Web Services)提供了一系列强大的无服务器服务,如 AWS Lambda、AWS Step Functions 和 AWS Elastic Load Balancer,这些服务极大地简化了应用程序的开发和部署过程。下面将详细介绍这些服务的特点、优缺点以及实际操作步骤。 #### 1. AWS Lambda 函数 ##### 1.1 无状态执行特性 AWS Lambda 函数设计为无状态的,每次调用都是独立的。这种架构从一个全新的状态开始执行每个函数,有助于提高可扩展性和可靠性。 #####

Rust数据处理:HashMaps、迭代器与高阶函数的高效运用

### Rust 数据处理:HashMaps、迭代器与高阶函数的高效运用 在 Rust 编程中,文本数据管理、键值存储、迭代器以及高阶函数的使用是构建高效、安全和可维护程序的关键部分。下面将详细介绍 Rust 中这些重要概念的使用方法和优势。 #### 1. Rust 文本数据管理 Rust 的 `String` 和 `&str` 类型在管理文本数据时,紧密围绕语言对安全性、性能和潜在错误显式处理的强调。转换、切片、迭代和格式化等机制,使开发者能高效处理文本,同时充分考虑操作的内存和计算特性。这种方式强化了核心编程原则,为开发者提供了准确且可预测地处理文本数据的工具。 #### 2. 使

并发编程中的锁与条件变量优化

# 并发编程中的锁与条件变量优化 ## 1. 条件变量优化 ### 1.1 避免虚假唤醒 在使用条件变量时,虚假唤醒是一个可能影响性能的问题。每次线程被唤醒时,它会尝试锁定互斥锁,这可能与其他线程竞争,对性能产生较大影响。虽然底层的 `wait()` 操作很少会虚假唤醒,但我们实现的条件变量中,`notify_one()` 可能会导致多个线程停止等待。 例如,当一个线程即将进入睡眠状态,刚加载了计数器值但还未入睡时,调用 `notify_one()` 会阻止该线程入睡,同时还会唤醒另一个线程,这两个线程会竞争锁定互斥锁,浪费处理器时间。 解决这个问题的一种相对简单的方法是跟踪允许唤醒的线

Rust应用中的日志记录与调试

### Rust 应用中的日志记录与调试 在 Rust 应用开发中,日志记录和调试是非常重要的环节。日志记录可以帮助我们了解应用的运行状态,而调试则能帮助我们找出代码中的问题。本文将介绍如何使用 `tracing` 库进行日志记录,以及如何使用调试器调试 Rust 应用。 #### 1. 引入 tracing 库 在 Rust 应用中,`tracing` 库引入了三个主要概念来解决在大型异步应用中进行日志记录时面临的挑战: - **Spans**:表示一个时间段,有开始和结束。通常是请求的开始和 HTTP 响应的发送。可以手动创建跨度,也可以使用 `warp` 中的默认内置行为。还可以嵌套

Rust项目构建与部署全解析

### Rust 项目构建与部署全解析 #### 1. 使用环境变量中的 API 密钥 在代码中,我们可以从 `.env` 文件里读取 API 密钥并运用到函数里。以下是 `check_profanity` 函数的代码示例: ```rust use std::env; … #[instrument] pub async fn check_profanity(content: String) -> Result<String, handle_errors::Error> { // We are already checking if the ENV VARIABLE is set

Rust编程:模块与路径的使用指南

### Rust编程:模块与路径的使用指南 #### 1. Rust代码中的特殊元素 在Rust编程里,有一些特殊的工具和概念。比如Bindgen,它能为C和C++代码生成Rust绑定。构建脚本则允许开发者编写在编译时运行的Rust代码。`include!` 能在编译时将文本文件插入到Rust源代码文件中,并将其解释为Rust代码。 同时,并非所有的 `extern "C"` 函数都需要 `#[no_mangle]`。重新借用可以让我们把原始指针当作标准的Rust引用。`.offset_from` 可以获取两个指针之间的字节差。`std::slice::from_raw_parts` 能从