image.png

书名 Rust编程之道 作者 张汉东中国
出版社 中国工信出版集团 电子工业出版社 阅读日期 2019年1月

2 语言精要

2.1 Rust语言基本构成

语言规范
编译器 rustc
核心库
标准库
包管理器

2.1.3 核心库

Rust 语言的语法由 核心库标准库 共同提供。其中 Rust 核心库是标准库的基础。
核心库中定义的是 Rust 语言的核心,不依赖于操作系统和网络等相关的库,甚至不知道堆分配,也不提供并发和IO。

可以通过在模块顶部引入#![no std]来使用核心库 。#![no std]
核心库和标准库的功能有一些重复,包括如下部分:基础的 trait,如 Copy、 Debug 、 Display 、 Option 等。

基本原始类型,如 bool、 char、 i8/u8 、 i16/u16 、 i32/u32 、 i64/u64 、 isize/usize 、 f32/f64 、 str、 array 、 slice 、 tuple 、 pointer 等。

常用功能型数据类型,满足常见的功能性需求,如 String 、 Vec 、 HashMap 、 Rc 、 Arc 、 Box 等。

常用的宏定义,如 println! 、 assert!、 panic!、 vec!等。

做嵌入式应用开发的时候,核心库是必需的

2.1.4 标准库

Rust标准库提供应用程序开发所需要的基础和跨平台支持

标准库包含的内容大概如下:

  • 与核心库一样的基本 trait、原始数据类型、功能型数据类型和常用宏等,以及与核心库几乎完全一致的 API
  • 并发、 IO 和运行时。 例如线程模块、用于消息传递的通道类型、 Sync trait 等并发模块,文件、 TCP 、 UDP、管道、套接字等常见 IO 。
  • 平台抽象。 OS 模块提供了许多与操作环境交互的基本功能,包括程序参数、环境变量 和目录导航:路径模块封装了处理文件路径的平台特定规则。
  • 底层操作接口,比如 std::mem、 std::ptr 、 std: :in trinsics 等,操作内存、指针、调用编 译器固有函数。
  • 可选和错误处理类型 Option 和 Result,以及各种选代器等。

2.2 语句与表达式

Rust 中的语法可以分成两大类:

  • 语句 ( Statement ) :要执行的一些操作和产生副作用的表达式。
  • 表达式 ( Expression ):主要用于计算求值。

语句又分为两种:

  1. 声明语句 ( Declaration statement ):用于声明各种语言项 (ltem),包括声明变量、静态变量、常量、 结构体、 函数等,以及通过 extern 和 use 关键字引入包和模块等。
  2. 表达式语句 ( Expression statement ):特指以分号结尾的表达式。此类表达式求值结果将会被舍弃, 并总是返回单元类型()单元类型拥有唯一的值, 就是它本身,为了描述方便,将该值称为单元值。 单元类型的概念来自 OCmal,它表示 “没有什么特殊的价值” 。 所以,这里将单元类型作为函数返回值, 就表示该函数无返回值。当然, 通常无返回值的函数默认不需要在函数签名中指定返回类型。
  1. fn main(){
  2. pub fn answer() ->(){
  3. let a = 40;
  4. let b = 2;
  5. assert_eq!(sum(a,b),42);
  6. }
  7. }

编译器解析代码次序

Rust编译器在解析代码时,如果碰到分号,就会继续向后执行;
如果碰到语句,则执行语句;
如果碰到表达式,则会对表达式求值;
如果分号后面什么也没有,就会补上单元值。

当遇到函数时,会将函数体的花括号识别为 Block Expression 块表达式。Block Expression由一对花括号和一系列的表达式组成。它总是返回块中最后一个表达式的值。

2.3 变量和绑定

Binding 绑定 : Identifier 标识符 和 Value 值之间的关联关系。

2.3.1 位置表达式和值表达式

Place Expression 位置表达式:表示内存位置的表达式。
(其他语言一般叫做LValue 左值)分别有几类:

  • 本地变量
  • 静态变量
  • 解引用(*expr)
  • 数组索引(expr[expr])
  • 字段引用(expr.field)
  • 位置表达式组合

通过位置表达式可以对某个数据单元的内存进行读写。主要是进行写操作,这也是位置表达式可以被赋值的原因。

Value Expression 值表达式:除了Place Expression 的表达式就是值表达式。
(其他语言一般叫做RValue 右值)
Value Expression 一般只引用了某个存储单元地址中的数据,它相当于数据值,只能进行读操作。

语义角度,Place Expression代表了持久性数据,值表达式代表了临时数据

表达式的求值过程一般在不同的上下文过程中,会有不同的结果。
求值上下文也分为:

  • Place Context 位置上下文
  • Value Context 值上下文

2.6.3 字符类型

Rust中,使用单引号定义字符 (char)类型。char 是一个 Unicode标量值,每个字符占用4个字节。

2.6.4 数组类型

Array是Rust内建的原始集合类型,数组特点是:

  • 数组大小固定
  • 元素同等类型
  • 默认不可改变

数组签名类型为 [T;N]
T 是一个范型标记;N 代表数组长度,是编译时常量。

2.6.5 范围类型

  1. fn main(){
  2. assert_eq!((1..5),std::ops::Range{start:1,end:5});
  3. println!("{:?}",(1..5));
  4. println!("{:?}",std::ops::Range{start:1,end:6});
  5. }

2.6.8 原生指针

指针:表示内存地址的类型。

Rust提供了多种类型的指针,包括 引用(Reference),原生指针(Raw Pointer),函数指针(fn Pointer)和智能指针(Smart Pointer)

Reference 本质上是一种 非空指针
Rust可以划分为 Safe Rust 和 Unsafe Rust 两部分。引用主要应用于Safe Rust中。在Safe Rust中,编译器会对引用进行借用检查,以保证内存安全和类型安全。
原生指针主要用于 Unsafe Rust中。直接使用原生指针是不安全的。比如原生指针可能指向一个Null,或者一个已经被释放的内存区域。因为使用原生指针的地方不在safe Rust的可控范围内,所以需要程序员自己保证安全。
rust支持两种原生指针:不可变原生指针 const T 和可变原生指针 mut T。

2.7 复合数据类型

Rust提供 4 种复合数据类型:

  • 元组(Tuple)
  • 结构体(Struct)
  • 枚举体(Enum)
  • 联合体(Union)

这4种复合数据类型都是 异构数据结构

2.7.1 元组

Tuple是一种 异构 有限 序列。