Variables and Mutability
默认情况下,变量是不可变的。在没有使用mut的情况下,若重复修改变量的值会产生error[E0384]: cannot assign twice to immutable variable x
。
Constants
同不可能变量相同,常量的值也不可修改。但是常量不允许使用mut,常量不仅在默认情况下是不可变的--它们始终是不可变的的。定义常量使用const关键字,而且必须在初始化时赋值,值只能是一个常量表达式。
const THREE_HOURS_IN_SECONDS: u32 = 60 * 60 * 3;
Rust 的常量命名约定是全部使用大写字母,单词之间有下划线。
Shadowing
声明一个同名新变量,覆盖先前的变量。
shadowing和使用mut存在两点不同,使用mut是不会改变变量类型,而使用let实际上是创建了一个同名新变量。且此变量可以不为之前的类型。
如下第一个spaces变量是字符串类型,第二个spaces变量是数字类型。使用let可以减少重新起名。但用mut无法做到这种事。
let spaces = " "; let spaces = spaces.len();
运行时错误:mismatched types
let mut spaces = " "; spaces = spaces.len();
Data Types
rust 中每个值都有特定的数据类型。scalar and compound。
rust 是一种静态类型语言,因此它必须在编译时知道所有变量的类型。编译器通常会根据值和使用它的方式来推断值的类型。但在存在多种类型的情况下,需指明具体类型。例如数字类型。
let guess: u32 = "42".parse().expect("Not a number!");
scalar
Scalar 用于表示单个值。rust中主要有四种类型:integers,floating-point numbers, Booleans, 以及characters。
integers
整数是没有小数部分的数字。i开头的为有符号的整数,u开头的为无符号的整数。
Length | Signed | Unsigned |
---|---|---|
8-bits | i8 | u8 |
16-bits | i16 | u16 |
32-bits | i32 | u32 |
64-bits | i64 | u64 |
128-bits | i128 | u128 |
arch | isize | usize |
当需要表示有符号数的时候,需使用Signed,有符号数使用二进制补码来存储(原码取反+1)。二者的取值范围如下:
进制 | 示例 |
---|---|
Decimal | 98_222 |
Hex | 0xff |
Octal | 0o77 |
Binary | 0b1111_0000 |
Byte (u8 only) |
b'A' |
注:数字间可以使用_为视觉分隔符。1_000的值等同于1000。
overflow
当使用u8类型时,值的范围为0-255,若将值赋为256,不管release还是debug都会报错 literal out of range for u8
。
但是要是换成此种写法,在debug mode下会产生不变,而在 release mode下,不会检查整数溢出,若发生溢出,Rust执行二进制补码进行包装,当值为u8类型时,256会变成0,257会变成1。程序不会panic,但是值可能不是期望值。
处理显式溢出,可以使用标准库的以下方法 :
-
wrapping_add 当overflow时,会自动回到最小值,结果和使用release相同,但是使Wrapping包装类可以在debug模式下使用,同时避免出现不可预期的结果。
-
使用checked_add方法。会在溢出时返回None,方便定位是否产生溢出。
3,使用overflowing_add。此方法会返回一个结果和一个布尔值来定位是否溢出,相较于wrapping_add多一个是否溢出的标记。
-
使用saturating_add。越界时数值为临界点的值。
Floating-Point Types
浮点数是带小数点的数字。Rust有f32和f64两种。浮点数都是有符号数,且默认为f64。
fn main() { let x = 2.0; // f64 let y: f32 = 3.0; // f32 }
Numeric Operations
rust数字类型支持所有基本数学运算,整数除法时,结果取最接近0的整数。
The Boolean Type
布尔类型一个字节,有true和false两种值。可以隐式和显式声明。
fn main() { let t = true; let f: bool = false; // with explicit type annotation }
The Character Type
char是rust最原始的类型。 字符型使用单引号指定文字,而非双引号。同时大小为4个字节,表示一个Unicode标量值,故而字符型不仅可以表示ASCII,也可以表示带音调的字母、中文、日文、韩文字符、emoji以及零宽空格。
Unicode标量值的范围 U+0000 到 U+D7FF 和 U+E000 到 U+10FFFF(含)。字符于rust中比较特殊。
compound Types
复合类型可以将多个值组合成一个类型。rust中有两种基本的符合类型:元组(tuples)和数组(arrays)。
The Tuple Type
元组是将多个具有多种类型的值组合成一个复合类型的通用方法。固定长度:声明后,它们的大小就不能增加或缩小。若要从元组中取单个值:1.通过模式匹配来解析元组值。 2.通过使用句点(.)后接索引来访问元素(从0开始)。
当一个元组没有任何值,那么它拥有一个特殊的名字-> unit。 这个值及其对应的类型都写作(),表示空值或空返回类型。一般用于函数无返回值时。
fn say_hi() -> () {
println!("Hi!");
}
// 显式返回
fn say_hi() -> () {
println!("Hi!");
return ();
}
The Array Type
数组每个元素必须具有相同的类型,Rust中数组具有固定长度。数组中的值在方括号内以逗号分隔。故而当数量固定时数组很有用。vector相较于数组更灵活,可以扩大或缩小大小。
Functions
函数的关键字为fn,main函数是所有程序的入口。rust中变量名与函数名都使用蛇形方式来定义:所有字母均小写,并用下划线分隔单词。
带参数的函数
函数签名中必须声明每个参数类型。多个参数之间用逗号隔开。
语句和表达式
语句是执行某些操作但没有返回值的指令。
表达式是计算结果值。
无法做到c语言中的 x=y=6;
表达式可以是语句的一部分:计算结果是表达式,调用函数是表达式,调用宏是表达式,用大括号创建的新作用域块是一个表达式。
同大多数行不同,该x+1行末尾没有分号。表达式不包括结束分号,若在表达式末尾添加分号,就成为了一个语句,就不再返回值。
带返回值的函数
Rust中,函数的返回值和函数体块中最终表达式的值同义。返回值需通过箭头(->)声明它们的类型。可以通过return关键字从函数中提前返回,但更多的函数会隐式返回最后一个表达式。
Control Flow
if Expressions
if 的条件必须是一个bool值,
if在let声明中使用(类似 int x = condition? 1:2)
因为变量必须有单一类型,而 Rust 需要在编译时明确地知道 number变量是什么类型。故if和else表达式结果需为同一类型。
loops
rust循环有三种:loop、while和for。
loop
循环标签必须以单引号开头。多级嵌套循环时,当在内循环中使用外循环的continue和break时。可以通过给外循环指定一个循环标签来实现。
while
条件循环。节省了loop中各种的if,else以及break代码。当条件为true时执行循环。
for
rust中最常用的循环结构。使用for遍历数组时,不需考虑数组的个数。减少了出现错误的可能性。
文章评论