Rust 从入门到摔门而出门 (二) 数据类型

90 阅读6分钟

Rust 从入门到摔门而出门 (二) 数据类型

Rust的数据类型有两种:标量数据类型和复合数据类型,

  • 标量数据类型只有一个值,有 整型、浮点型、布尔、字符 四种类型。
  • 复合数据类型多个值组合成一个类型,有 元组和数组。

标量类型

整型

整数是一个没有小数的数组,在Rust中整数分为有无符号(-),代表数字能否负值,有符号数以补码形式存储。

Rust中数字类型默认使用 i32。

长度有符号无符号
8-biti8u8
16-biti16u16
32-biti32u32
64-biti64u64
128-biti128u128
archisizeusize

isize 和 usize 类型依赖运行程序的计算机架构:64 位架构上它们是 64 位的,32 位架构上它们是 32 位的。

取值范围:

  • i8的取值范围为 -128 到 127
  • u8的取值范围为 0 到 255
  • i16的取值范围为 -32768 到 32767
  • u16的取值范围为 0 到 65535
  • i32的取值范围为 -2147483648 到 2147483647
  • u32的取值范围为 0 到 4294967295
  • i64的取值范围为 -9223372036854775808 到 9223372036854775807
  • u64的取值范围为 0 到 18446744073709551615
  • i128的取值范围为 -170141183460469231731687303715884105728 到 170141183460469231731687303715884105727
  • u128的取值范围为 0 到 340282366920938463463374607431768211455

isize 和 usize 的取值范围依赖于他在运行的计算机架构。

整型中使用不同进制:

数字字面值例子
十进制98_123
十六进制0xff
八进制0o77
二进制0b1111_0000
单字节字符(仅限于u8)b'a'

整型溢出

let a: u8 = 256; 

在rust中定义一个变量a:u8,u8的取值范围是 0 到255,如果赋值256 超出取值范围,被称为整型溢出这会导致两种情况:

  • debug编译模式时 Rust 检查这类问题并使程序 panic,因为错误而退出。
  • 使用 --release 构建时 使用 --release flag 在 release 模式中构建时,Rust 不会检测会导致 panic 的整型溢出。相反发生整型溢出时,Rust 会进行一种被称为二进制补码的操作。简而言之,比此类型能容纳最大值还大的值会回绕到最小值,值 256 变成 0,值 257 变成 1,依此类推。程序不会 panic,不过变量可能也不会是你所期望的值。依赖整型溢出 wrapping 的行为被认为是一种错误。

浮点型

在Rust中的浮点型,有两种 f32 和 f64,分别占 32位和64位。Rust中默认类型是 f64,在目前的计算机中 f64 和 f32 速度几乎一样,不过精度更高,所有的浮点型都是有符号的。

fn main(){
    let x = 1.2; // f64
    
    let y: f64 = 2.4; // f32
}

浮点数采用 IEEE-754 标准表示。f32 是单精度浮点数,f64 是双精度浮点数。

数值运算

Rust中支持 加法、减法、乘法、除法和取余。整数除法会向零舍入到最接近的整数。

fn main() {
    // addition
    let sum = 5 + 10;
    println!("数字结果 sum {sum}"); 
    //数字结果 sum 15
    
    // subtraction
    let difference = 95.5 - 4.3;
    println!("数字结果 difference {difference}"); 
    //数字结果 difference 91.2

    // multiplication
    let product = 4 * 30;
    println!("数字结果 product {product}"); 
    // 数字结果 product 120

    // division
    let quotient = 56.7 / 32.2;
    println!("数字结果 quotient {quotient}"); 
    // 数字结果 quotient 1.7608695652173911

    let truncated = -5 / 3;
    println!("数字结果 truncated {truncated}"); 
    // 数字结果 truncated -1

    let truncated2 = -5.0 / 3.0;
    println!("数字结果 truncated {truncated2}"); 
    // 数字结果 truncated  -1.6666666666666667
    
    // remainder
    let remainder = 43 % 5;
    println!("数字结果 remainder {remainder}"); 
    //数字结果 remainder 3
}

在上段代码中 -5/3 结果是 -1, 在Rust中整数除法会 向零舍入,取整。 如果代码想要避免这种情况可以转成浮点数 -5.0 / 3.0 结果是 -1.6666666666666667。

布尔值

Rust中的布尔值和其他大部分语言一样,有两个值 truefalse,使用 bool标识。

let t = true;

let f: bool = false;

字符类型

Rust 的 char 类型是语言中最原生的字母类型。

fn main() {
    let str = 'string';
    let str2: char = 'string'; // with explicit type annotation
    let heart_eyed_cat = '😝';
}

复合类型

复合类型可以将多个值组合成一个类型。Rust 有两个原生的复合类型:元组(tuple)和数组(array)。

元组

元组是一个将多个其他类型的值组合进一个复合类型的主要方式,元组的长度固定:一旦声明,其长度不会增大或缩小。

let tup: (i32, f64, char) = (123, 3.14, '哈哈');

上段代码中声明了 元组 tup,指有三个可以设置不同的数据类型。

let tup: (i32, f64, char) = (123, 3.14, '哈哈');
let (a, b, c) = tup;
println!("a: {a}, b: {b}, c: {c}");

上段代码中将元组进行了解构。

let tup: (i32, f64, char) = (123, 3.14, '哈哈');
let a = tup.0;
let b = tup.1;
let c = tup.2;

上段代码通过索引的方式(.),进行访问获取值。

不带任何值的元组,在Rust中叫做单元元组。这种值以及对应的类型都写作 (),表示空值或空的返回类型。如果表达式不返回任何其他值,则会隐式返回单元值。

数组类型

数组也包含多个值,和元组不同的是,数组的每个元素的数据类型必须相同。Rust中数组的长度是固定的,这是与一些其他语言中的数组不同。

let arr = [ 1, 2, 3, 4, 5 ];

let arr2: [i32; 5] = [ 1, 2, 3, 4, 5 ];

let arr3 = [11; 5];

上段代码:

  • 变量 arr2的 [i32; 5] 这里 i32 表示每个值的数据类型,分号后的 5 表示该数组包含5个元素
  • 变量 arr3的 [11; 5] 表示生成数组长度5,初始值为 11。等同于let arr3 = [ 11, 11, 11, 11, 11 ]; 相同的效果,[11; 5] 的写法更加简洁。
访问素组元素
let arr = [ 1, 2, 3, 4, 5 ];

let a = arr[0];
let b = arr[1];

数组是可以在栈上分配的已知固定大小的单个内存块。可以使用索引来访问数组的元素,Rust和大部分语言一样从0开始。