title | tags | |||
---|---|---|---|---|
2. Base Type |
|
在这一章节中,我们将通过具有详细说明的实例,探索 Rust 中的基础语法元素。我们会覆盖变量和可变性、数据类型(包括标量和复合类型)。
在 Rust 中,变量默认是不可变的。这意味着一旦值被赋予一个变量,你就不能更改这个值。不过,你可以使用 mut
关键字来使变量可变。
let x = 5;
println!("The value of x is: {}", x);
// x = 6; // 这行会导致编译错误,因为 x 不可变
let mut y = 5;
println!("The value of y is: {}", y);
y = 6; // 这是允许的,因为 y 是可变的
println!("The value of y is: {}", y);
Rust是静态类型语言,意味着所有的变量类型都必须在编译时已知。编译器通常可以根据值和使用方式推导出类型,Rust 数据类型大致可以分为两大类:标量和复合类型。
标量类型代表单一值。如前面所提到的,Rust 有四种基本的标量类型:整数、浮点数、布尔值和字符。
整数是没有小数部分的数字。在 Rust 中,整数类型分为有符号和无符号两种。例如,你之前见过的i32
类型代表有符号的32位整数(i
是英文单词integer
的首字母,意味着整数)。与之对应的是u
前缀,代表无符号(unsigned
)类型。以下是 Rust 中可用的内置整数类型:
长度 | 有符号类型 | 无符号类型 |
---|---|---|
8位 | i8 |
u8 |
16位 | i16 |
u16 |
32位 | i32 |
u32 |
64位 | i64 |
u64 |
128位 | i128 |
u128 |
视架构而定 | isize |
usize |
对于有符号类型,其规定的数字范围是-(2^(n-1))
到2^(n-1) - 1
,其中n
是位数。例如,i8
可以存储的数字范围从-128
到127
。而无符号类型的范围是从0
到2^n - 1
,因此u8
的范围是从0
到255
。
至于isize
和usize
,它们的大小取决于运行程序的计算机 CPU 类型:如果 CPU 是32位的,它们就是32位;如果 CPU 是64位的,那么它们就是64位。
整数的表述方法有以下几种:
- 十进制:没有前缀,例如98_222(_用于提高可读性,没有实际值)
- 十六进制:0x前缀,例如0xff
- 八进制:0o前缀,例如0o77
- 二进制:0b前缀,例如0b1111_0000
- 字节(仅限于u8类型):b'前缀,例如b'A'
let x: i32 = -123;
let y: u32 = 123;
println!("x is {}, y is {}", x, y);
Rust提供了两种精度的浮点类型:单精度f32
和双精度f64
。默认情况下,浮点数类型是f64
,因为它同时提供了很好的精度和速度。
类型 | 精度 |
---|---|
f32 |
单精度(32位)浮点数 |
f64 |
双精度(64位)浮点数 |
let x = 2.0; // 此处没有指定类型,编译器自动推导出 x 类型是f64(默认的float)
let y: f32 = 3.0; // 显式声明为 f32
println!("x is {}, y is {}", x, y);
let x1 = 2.0; // 此处没有指定类型,但是下面语句x1和一个f32类型做加法运算,编译器自动推导出x1类型是f32
let y1: f32 = 3.0; // 显式声明为 f32
let z1 = x1 + y1;
println!("x1 is {}, y1 is {} z1 is {}", x1, y1, z1);
let t = true;
let f: bool = false; // 显式类型声明
println!("t is {}, f is {}", t, f);
字符,由于 Unicode 都是 4 个字节编码,因此字符类型也是占用 4 个字节:
let c = 'z';
let z = 'ℤ';
let heart_eyed_cat = '😻';
println!("c is {}, z is {}, heart_eyed_cat is {}", c, z, heart_eyed_cat);
println!("字符'c'占用了{}字节的内存大小",std::mem::size_of_val(&c));
在 Rust 中,String
字符串类型的长度取决于使用的编码集,默认情况下,Rust 使用 UTF-8 编码,一个字符占用 1~4 个字节,而 char
字符类型占用 4 个字节的存储空间,即使有些字符在特定编码集下只需要 1~3 个字节表示,Rust 也会将其扩展为 4 个字节。这样做的好处是:
- 保证所有
char
值在内存中占用固定大小,有利于内存对齐和访问效率。 - 避免编码转换开销,直接使用 4 字节值可以高效处理字符。
- 足够表示 Unicode 标量值所需的全部码位,确保未来的兼容性。
复合类型可以将多个值组成一个类型。Rust 主要包括元组(tuple)和数组(array)两种复合类型。
元组是将多种类型的多个值组合到一个复合类型中的一种基本方式, 长度是固定的。
let tup: (i32, f64, u8, char) = (-500, 6.4, 1, 'z');
let (w, x, y, z) = tup; // 解构元组
println!("The value of x is: {}", x);
将多个值组合在一起的另一种方式就是使用数组。与元组不同,数组的每个元素必须具有相同的类型,数组的长度也是固定的。
let a = [1, 2, 3, 4, 5];
let first = a[0];
let second = a[1];
println!("The first element is {}, the second element is {}", first, second);
这一章主要学习了 Rust 的基本数据类型,整数、浮点数、布尔值、字符四种基本的标量类型,元组、静态数组两种复合类型。