mirror of
https://github.com/RustyCab/LearnRustEasy.git
synced 2026-02-03 10:13:23 +08:00
Merge pull request #19 from geometryolife/fix-typo
This commit is contained in:
@@ -6,7 +6,7 @@ Rust是静态类型语言,编译时就必须知道所有变量的类型。根
|
||||
|
||||
标量类型包括:整型、浮点型、布尔类型和字符类型。
|
||||
|
||||
### 3.2.1.1 整型和浮点型
|
||||
### 1. 整型和浮点型
|
||||
|
||||
Rust中的整型和浮点型如下:
|
||||
|
||||
@@ -78,7 +78,7 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2.1.2 布尔型
|
||||
### 2. 布尔型
|
||||
|
||||
Rust中的布尔型用`bool`表示,有两个可能的值,为`true`和`false`。布尔类型使用的场景主要是条件表达式(控制流的内容),使用如下:
|
||||
|
||||
@@ -103,7 +103,7 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2.1.3 字符类型
|
||||
### 3. 字符类型
|
||||
|
||||
Rust用`char`表示字符类型,用于存放单个unicode字符,占用4个字节空间。当存储`char`类型数据时,Rust会将其转换为utf-8编码的数据存储。`char`字面量是单引号包裹的任意单个字符,字符类型使用示例如下:
|
||||
|
||||
@@ -119,7 +119,7 @@ fn main() {
|
||||
|
||||
复合类型是将多个值组合成一个类型。Rust有两个原生复合类型:元组和数组。
|
||||
|
||||
### 3.2.2.1 元组
|
||||
### 1. 元组
|
||||
|
||||
圆括号以及其中逗号分割的值列表组成元组,定义一个元组方式如下:
|
||||
|
||||
@@ -158,7 +158,7 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2.2.2 数组
|
||||
### 2. 数组
|
||||
|
||||
数组中的每个元素的类型必须相同,数组的长度是固定的,数组的定义方式如下:
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 3.3 函数
|
||||
|
||||
## 3.3.1. 函数定义
|
||||
## 3.3.1 函数定义
|
||||
|
||||
fn关键字、函数名、函数参数名及其类型(如果有的话)、返回值类型(如果有的话)组成函数签名, 加上由一对花括号包含的函数体组成函数。例子如下:
|
||||
`fn`关键字、函数名、函数参数名及其类型(如果有的话)、返回值类型(如果有的话)组成函数签名,加上由一对花括号(`{}`)包裹的函数体组成函数。例子如下:
|
||||
|
||||
```rust
|
||||
// 一个没有参数,也没有返回值的函数
|
||||
@@ -53,26 +53,26 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
## 3.3.2. 语句和表达式
|
||||
## 3.3.2 语句和表达式
|
||||
|
||||
Rust中,语句是执行一个操作但不返回值的指令,表达式则计算并产生一个值。
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let a = 1u32; // "1u32"就是一个表达式, “let a = 1u32;”则是一个语句
|
||||
let b = a + 1;// “a + 1”就是一个表达式,“let b = a + 1;”则是一个语句
|
||||
let a = 1u32; // "1u32"就是一个表达式,而“let a = 1u32;”则是一个语句
|
||||
let b = a + 1; // “a + 1”就是一个表达式,而“let b = a + 1;”则是一个语句
|
||||
// 下面的代码中,
|
||||
// “ b + d ”是一个表达式,
|
||||
// “b + d”是一个表达式
|
||||
let c = {
|
||||
let d = 2u32;
|
||||
b + d //注意:这里是没有分号的
|
||||
b + d // 注意:这里是没有分号的
|
||||
}; // c = 4
|
||||
}
|
||||
```
|
||||
|
||||
## 3.3.3. 函数返回值
|
||||
## 3.3.3 函数返回值
|
||||
|
||||
- 使用return指定返回值,如下:
|
||||
- 使用`return`指定返回值,如下:
|
||||
|
||||
```rust
|
||||
fn sum(a: u32, b: u32) -> u32 {
|
||||
@@ -88,22 +88,23 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
特别的return关键字不指定值时,表示返回的是(),如下:
|
||||
特别地,`return`关键字不指定值时,表示返回的是`()`,如下:
|
||||
|
||||
```rust
|
||||
fn my_function() -> () {
|
||||
println!("some thing");
|
||||
return; //等价于 “return ()”
|
||||
return; // 等价于“return ()”
|
||||
}
|
||||
```
|
||||
|
||||
- 不使用return关键字,将返回最后一条执行的表达式的计算结果,如下:
|
||||
- 不使用`return`关键字,将返回最后一条执行的表达式的计算结果,如下:
|
||||
|
||||
```rust
|
||||
fn sum(a: u32, b: u32) -> u32 {
|
||||
println!("a is {:?}", a);
|
||||
println!("b is {:?}", b);
|
||||
|
||||
a + b //注意,是没有加分号的
|
||||
a + b // 注意,是没有加分号的
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
/*
|
||||
* 块注释:
|
||||
* 函数名:sum
|
||||
* 参数: a,b
|
||||
* 返回值类型: u32
|
||||
* 参数:a,b
|
||||
* 返回值类型:u32
|
||||
*/
|
||||
fn sum(a: u32, b: u32) -> u32 {
|
||||
a + b
|
||||
@@ -99,4 +99,4 @@ cargo doc --open
|
||||
|
||||
将打开上面代码里面文档注释生成的文档,如下图:
|
||||
|
||||

|
||||

|
||||
|
||||
@@ -73,7 +73,7 @@ Rust中的控制流结构主要包括:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
// 一直循环打印 again
|
||||
// 一直循环打印 again!
|
||||
loop {
|
||||
println!("again!");
|
||||
}
|
||||
@@ -91,12 +91,14 @@ Rust中的控制流结构主要包括:
|
||||
counter += 1;
|
||||
|
||||
if counter == 10 {
|
||||
break; // 将终止循环
|
||||
break; // 将终止循环
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
上面的代码将打印10次,遇到`break`后终止循环。另外,`break`也可以返回值,如下:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let mut counter = 0;
|
||||
@@ -125,7 +127,7 @@ Rust中的控制流结构主要包括:
|
||||
break;
|
||||
}
|
||||
if x % 2 == 0 {
|
||||
continue; //将直接跳到下一轮循环
|
||||
continue; // 将直接跳到下一轮循环
|
||||
}
|
||||
println!("{}", x);
|
||||
}
|
||||
@@ -134,7 +136,7 @@ Rust中的控制流结构主要包括:
|
||||
|
||||
## 3.5.3. while条件循环
|
||||
|
||||
- `while`条件循环执行代码,当条件不满足后结束循环,如下:
|
||||
- `while`条件循环执行代码,当条件不满足时结束循环,如下:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
|
||||
## 3.6.1 Rust程序内存布局
|
||||
|
||||

|
||||

|
||||
|
||||
上图是一张linux系统上Rust程序的内存布局图。在linux操作系统中,会划分固定的区域给内核使用,即上图中的内核空间;应用程序使用的是用户空间。
|
||||
上图是一张Linux系统上Rust程序的内存布局图。在Linux操作系统中,会划分固定的区域给内核使用,即上图中的内核空间;应用程序使用的是用户空间。
|
||||
|
||||
Rust程序使用的内存空间分为如下:
|
||||
|
||||
- 只读代码区(Instructions):存放可执行代码的区域。
|
||||
- 只读数据区(Literals):存放代码的文字常量的区域。
|
||||
- 静态数据区(Static Data):一般的静态函数、静态局部变量、静态全局变量的存放区域,在程序启动的时候初始化。
|
||||
@@ -15,10 +16,9 @@ Rust程序使用的内存空间分为如下:
|
||||
|
||||
## 3.6.2 栈和堆
|
||||
|
||||
### 1.栈和栈帧
|
||||
### 1. 栈和栈帧
|
||||
|
||||
“栈和栈帧属于操作系统的概念,由操作系统进行管理,栈空间以后进先出的顺序存储数据。将数据放到栈上就做入栈,将数据移出栈就做出栈。
|
||||
每次调用函数时,操作系统会在栈顶创建一个栈帧来保存函数的上下文数据(主要是函数内部声明的局部变量),函数返回时返回值也会存储在该栈帧中。当函数调用者取得该函数返回值后,栈帧会被释放。”引用自《Rust入门秘籍》。
|
||||
> “栈和栈帧属于操作系统的概念,由操作系统进行管理,栈空间以后进先出的顺序存储数据。将数据放到栈上就做入栈,将数据移出栈就做出栈。每次调用函数时,操作系统会在栈顶创建一个栈帧来保存函数的上下文数据(主要是函数内部声明的局部变量),函数返回时返回值也会存储在该栈帧中。当函数调用者取得该函数返回值后,栈帧会被释放。”引用自《Rust入门秘籍》。
|
||||
|
||||
```rust
|
||||
fn f1(a: i32, b: i32) -> i32 {
|
||||
@@ -42,17 +42,17 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
对于上面的代码,在执行第17行和第18行的栈帧示意图如下:
|
||||
对于上面的代码,在执行`let _r = f1(a, b);`和`let _r = f2(a, b);`这两行代码时的栈帧示意图如下:
|
||||
|
||||

|
||||

|
||||
|
||||
这里需要注意的是两个帧对应同样的内存地址,这是因为在调用完f1函数后,其对应的栈帧释放(释放的实际意义就是这段内存可以被重新分配了),然后调用f2函数为其分配栈帧时从同样的地址进行分配。
|
||||
这里需要注意的是两个帧对应同样的内存地址,这是因为在调用完`f1`函数后,其对应的栈帧释放(释放的实际意义就是这段内存可以被重新分配了),然后调用`f2`函数为其分配栈帧时从同样的地址进行分配。
|
||||
|
||||
### 2. 堆
|
||||
|
||||
堆空间和栈空间不同,不由操作系统管理,在需要时申请,不需要时释放。申请和释放堆内存是一件困难的事情,尤其当程序代码较多时。只申请堆内存而不释放会造成内存泄露,内存泄露过多会造成内存耗尽而崩溃。错误的释放在使用的内存也会造成程序运行错误(或直接无法运行)。
|
||||
堆空间和栈空间不同,不由操作系统管理,在需要时申请,不需要时释放。申请和释放堆内存是一件困难的事情,尤其当程序代码较多时。只申请堆内存而不释放会造成内存泄露,内存泄露过多会造成内存耗尽而崩溃。错误地释放在使用的内存也会造成程序运行错误(或直接无法运行)。
|
||||
|
||||
有些编程语言使用提供垃圾管理回收器(GC)来自动回收不再使用的堆内存,有些语言必须完全由程序员在代码中手动申请和释放内存。
|
||||
有些编程语言提供垃圾管理回收器(GC)来自动回收不再使用的堆内存,有些语言必须完全由程序员在代码中手动申请和释放内存。
|
||||
|
||||
Rust没有GC,但通过其独特的机制管理内存,程序员不用手动申请和释放堆内存。
|
||||
|
||||
@@ -60,8 +60,8 @@ Rust没有GC,但通过其独特的机制管理内存,程序员不用手动
|
||||
|
||||
栈中存储的所有数据都必须占用(在编译时就)已知且固定的大小。编译时大小未知或可能变化的数据,存储在堆上。
|
||||
|
||||
数据存放到栈上时,是直接将数据放到栈内存。
|
||||
数据存放到栈上时,是直接将数据放到栈内存的。
|
||||
|
||||
当数据需要存放到堆上时,内存分配器则是根据数据的大小,在堆内存找到合适大小的空区域存放,把它标记为已使用,并返回一个表示该位置地址的指针。该指针存储在栈上,当需要访问具体的数据时,必须先访问指针,然后通过指针找到堆上的位置,从而访问数据。这个过程可以用下图表示:
|
||||
|
||||

|
||||

|
||||
|
||||
Reference in New Issue
Block a user