From 75f4100132d69f21ab737192b828580397f9dd30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BB=A4=E7=8B=90=E4=B8=80=E5=86=B2?= <43949039+anonymousGiga@users.noreply.github.com> Date: Wed, 17 May 2023 11:16:57 +0800 Subject: [PATCH] Update chapter_3_2.md --- src/chapter_3/chapter_3_2.md | 207 +++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) diff --git a/src/chapter_3/chapter_3_2.md b/src/chapter_3/chapter_3_2.md index 8b13789..7ffe702 100644 --- a/src/chapter_3/chapter_3_2.md +++ b/src/chapter_3/chapter_3_2.md @@ -1 +1,208 @@ +## 3.2 基本数据类型(Basic Data Type) +Rust是静态类型语言,编译时就必须知道所有变量的类型。根据值以及其使用方式,Rust编译器通常能自动推导出变量的类型。 +Rust有两种数据类型子集,分别是:标量(scalar)类型和复合(compound)类型。 + +### 3.2.1 标量类型 +标量类型包括:整型、浮点型、布尔类型和字符类型。 + +- 整型和浮点型 + +Rust中的整型和浮点型如下: +长度 +有符号 +无符号 +浮点型 +8 bit +i8 +u8 + +16 bit +i16 +u16 + +32 bit +i32 +u32 +f32 +64 bit +i64 +u64 +f64 +128 bit +i128 +u128 + +arch +isize +usize + +说明:isize和usize的长度是和平台相关,如果CPU是32位的,则这两个类型是32位的,如果CPU是64位的,则这两个类型是64位的。 + +上面的表格中,f32和f64为浮点型,其它为整型。浮点型和整型一起构成数值型。 +(1)可以在数值字面量后面加上类型表示该类型的数值,如下: +``` +fn main(){ + let _a = 33u32; // 直接加类型后缀 + let _b = 33_i32; // 使用_分隔数值和类型 + let _c = 33_isize; + let _d = 33_f32; +} +``` +(2)可以数值的任意位置使用下划线分割来增强可读性,如下: +``` +fn main(){ + let _a = 10_000_000u32; + let _b = 1_234_3_u32; + let _c = 1_33_333f32; +} +``` +(3)当不明确指定变量的类型,也不明确指定数值字面量的类型后缀时,Rust默认将整数当做i32类型,将浮点数当做f64类型,如下: +``` +fn main(){ + let _a = 33; // 等价于 let _a: i32 = 33; 等价于 let _a = 33i32; + let _b = 64.123; // 等价于let _b: f64 = 64.123; 等价于 let _b = 64.123f64; +} +``` +(4)Rust使用0b表示二进制、0o表示八进制、0x表示十六进制,如下: +``` +fn main(){ + let a: u32 = 0b101; // 二进制整数 + let b: i32 = 0o17; // 八进制整数 + let c: u8 = 1; // 十进制 + let d: i32 = 0xac; // 十六进制整数 + println!("{}, {}, {}, {}", a, b, c, d); // 5, 15, 1, 172 +} +``` +(5)Rust中所有的数值类型都支持基本数学运算:加、减、乘、除、取余,如下: +``` +fn main() { + let sum = 5 + 10; + let difference = 95.5 - 4.3; + let product = 4 * 30; + let quotient = 56.7 / 32.2; + let truncated = -5 / 3; // 结果为 -1 + let remainder = 43 % 5; +} +``` + +- 布尔型 +Rust中的布尔型用bool表示,有两个可能的值,为true和false。布尔类型使用的场景主要是条件表达式(控制流的内容),使用如下: +``` +fn main() { + // 定义方式 + let a: bool = true; + let b: bool = false; + + // 使用场景 + if a { + println!("a is true"); + } else { + println!("a is false"); + } + + if b { + println!("b is true"); + } else { + println!("b is false"); + } +} +``` + +- 字符类型 +char类型用于存放单个unicode字符,占用4个字节空间。当存储char类型数据时,Rust会将其转换为utf-8编码的数据存储。char字面量是单引号包含的任意单个字符,字符类型使用示例如下: +``` +fn main() { + let c: char = 'z'; + let x: char = 'x'; + let heart_eyed_cat: char = '😻'; +} +``` + +### 3.2.2. 原生复合类型 +复合类型是将多个值组合成一个类型。Rust有两个原生复合类型:元组和数组。 + +- 元组 +圆括号以及其中逗号分割的值列表组成元组,定义一个元组方式如下: +``` +fn main() { + let tup: (i32, f64, u8) = (500, 6.4, 1); +} +``` +可以将元组重新结构到变量上,如下: +``` +fn main() { + let tup = (500, 6.4, 1); + let (x, y, z) = tup; + //接下来你可以使用x、y、z +} +``` +也可以直接使用元组的元素,如下: +``` +fn main() { + let x: (i32, f64, u8) = (500, 6.4, 1); + let first = x.0; + let second = x.1; + let third = x.2; +} +``` + +不带任何值的元组,称为unit类型(单元元组),可以代表空值或者空的返回类型,如下: +``` +fn main() { + let x: () = (); // 将值()保存到类型为()的变量x中 +} +``` + +- 数组 +数组中的每个元素的类型必须相同,数组的长度是固定的,数组的定义方式如下: +``` +fn main() { + let a = [1, 2, 3, 4, 5]; //直接写数组的值 + let b: [i32; 5] = [1, 2, 3, 4, 5]; //显示指定数组的类型和长度 + let c: [i32; 5] = [3; 5]; //数组每个元素为同样的值,等价于let a = [5, 5, 5, 5, 5]; +} +``` +数组通过索引来访问元素,索引从0开始计数,如下: +``` +fn main() { + let a = [1, 2, 3, 4, 5]; + + let first = a[0]; // first = 1 + let second = a[1]; // second = 2 +} +``` +Rust中,访问无效的索引元素会报错,如下: +``` +fn main() { + let a = [1, 2, 3, 4, 5]; + let b = a[5]; // 错误,只能放为0-4,所以这个代码将无法编译 +} +``` + +### 3.2.3 类型转换 (少一个From, Into, TryFrom, TryInto) + +Rust中可以使用as进行类型转换。 + +- 数值类型之间默认不会隐式转换,如果要转换,则需手动使用as进行转换。 +- bool类型可以转换为各种数值类型,false对应0,true对应1。 +- 可以通过as将char类型转换为各种整型,目标类型小于4字节时,会从高位截断。 +- 可以通过as将u8转换为char类型。 +- 可以使用std::char::from_u32将u32转换为char类型。 +- 可以使用std::char::from_digit将十进制整型转换为char类型。 +``` +fn main() { + // 数值类型的转换 + assert_eq!(10i8 as u16, 10u16); + assert_eq!(123u16 as i16, 123i16); + // bool类型转换 + assert_eq!(false as u32, 0u32); + assert_eq!(true as i8, 1i8); + // char类型相关转换 + assert_eq!('我' as i32, 25105i32); // char转换到i32 + assert_eq!('是' as u8, 47u8); // char转换到u8,会被截断 + assert_eq!(97u8 as char, 'a'); // u8转换到char + assert_eq!(std::char::from_u32(0x2764).unwrap(), '❤'); + assert_eq!(std::char::from_digit(4, 10).unwrap(), '4'); +} +```