笔记-Rust的基本类型1 : 机器类型及元组

490 阅读5分钟

Rust 类型的基础

Rust 类型的基础是一组固定宽度的数值类型,以及布尔类型和字符类型。基本类型包括:机器类型,元组(tuple),指针类型,数组、向量和切片,字符串类型。

机器类型

  1. 整数:无符号整数(u8, u16, u32, u64),有符号整数(i8, i16, i32, i64),
  2. 浮点数(f32, f64),
  3. 机器字(usize, isize):指的是运行代码的机器上内存地址的宽度,通常是32位或64位。
位数无符号整数有符号整数浮点数值
8u8i8
16u16i16
32u32i32f32
64u64i64f64
机器字usizeisize

整数类型

(1.1) 整数范围

  • 无符号数范围: 0 到 2的n次方 - 1;
  • 有符号数范围: -2的n-1次方 到 2的n-1次方 - 1。
  • 机器字:精度取决于目标机器的寻址空间大小:32位机器上是32位长,64位机器上是64位长。

(1.2) 一些特点

  • 整数字面量可以通过一个后缀表示类型。例如,32u8, 1980usize, -20i32。
  • 整数字面量可以使用前缀 0x、0o、0b 分别表示 16进制,8进制,和二进制。例如:oxcafeu32,0o106。
  • 整数(不论进制)长度较长时,为了可读性,可以在数字之间插入下划线。比如:21_485_295i32,0b0010_1010。
  • 数组索引必须是 usize 值。数组或向量的长度,也用 usize 表示。
  • 通常使用 u8 类型表示字节值;从 File 或 Socket 读取数据拿到的是 u8 值数据流。

(1.3) 整数溢出

  1. 在调试构建中,编译器会检查算术操作是否有整数溢出。 let b = std::i32::MAX + 1; // 发生panic, 会溢出
  2. 在发布构建中,这个操作会翻转为最小的 i32 负值。
  3. 建议使用: let a:i32 = std::i32::MAX; let b = a.wrapping_add(1);

(1.4) 字节字面量

  • Rust还提供了字节字面量(byte literal),使用字符字面量表示 u8 值。字节字面量中只能出现ASCII编码的字符。例如:let c:u8 = b'x'; // 此处c为120u8。
  • 某些特殊字符,需要进行转义。 例如:
    let c = b'\''; // 单引号('),39u
    let c = b'\\'; // 反斜杠(\),92u8
    let c = b'\n'; // 换行,10u8
    let c = b'\r'; // 回车, 13u8
    let c = b'\t'; // 制表符, 9u8
  • 反过来,对于难写或难读的字符,可以用十六进制写出他们的编码。
    let d = b'\x41';  // 十六进制41这个数字,表示的字符,的字面量的u8数字。ASCII 不容易表示的字符,只能直接写成数字了。除非想强调是 ASCII 字符,否则直接写数字就行了。
    let e: char = b'\x41' as char;  // 这个数字代表的 char。

(1.5) 部分整数函数

    assert_eq!(2u16.pow(3), 8);
    assert_eq!((-5i32).abs(), 5);
    assert_eq!(0b10_1101u8.count_ones(), 4);
    let aa = -100i32;
    println!("aa.is_negative = {}", aa.is_negative());  // aa.is_negative = true

2. 浮点数

  • Rust支持单、双精度浮点类型,分别为 f32, f64。
  • 如果浮点字面量中没有类型后缀,那么rust会根据上下文推断是 f32 还是 f64,若两种情况都有可能,则默认是 f64。
  • 浮点数通用形式:31415.926e-4f64 ,组成包括:整数部分(31415) + 小数部分(.926) + 指数(e-4) + 类型后缀(f64)。
  • 部分浮点函数:
    assert_eq!(5f32.sqrt() * 5f32.sqrt(), 5.0);
    assert_eq!(-1.0f64.floor(), -1.0);
    assert!((-1.0/std::f32::INFINITY).is_sign_negative());

3. 布尔类型

  • 布尔(bool)类型值有两个值: true 和 false。
  • Rust的 as 操作符 可以把 bool 值转换为整数类型。
    assert_eq!(true  as u8, 1);
    assert_eq!(false as u8, 0);
    
  • 但是as不能反向转换,不能从数值 转换为 布尔值,除非使用表达式(如 a!= 0)。

4. 字符类型

  • 字符类型 char 以 32 位值的形式表示单个 Unicode 字符。

  • Rust 使用 char 类型表示单个字符,但对字符串或文本流使用 UTF-8 编码。因此,String 将其文本表示为一个 UTF-8 字节的序列,而不是字符(char)的数组。

    println!(" {}", std::mem::size_of::<char>()); // output: 4
    let q1: char = 'a';
    let q2: char = '好';
    let s: String = "好a".to_string();
    println!("{}, {}, {}", q1.len_utf8(), q2.len_utf8(), &s.len()); // output: 1, 3, 4
    
  • Rust 从不隐式地在 char 与其他类型直接进行转换. 若有需要,可以使用 as 操作符。在char 通过 as 转其他类型时,若目的类型小于 32 位,字符值的高位(upper bits) 则会被截断。

  • 反过来,数字中,只有 u8 类型的整数可以直接转换为 char 类型。其他类型的数值,可能包含了非法的 Unicode 码点。 使用 std::char::from_u32 函数 会得到 Option 值。

  • 字符类型的常用方法:

    println!("{}", '*'.is_alphabetic()); // false
    println!("{}", 'β'.is_alphabetic()); // true
    println!("{:?}", '5'.to_digit(10)); // Some(5)
    println!("{:?}", std::char::from_digit(3, 10)); // Some('3')
    println!("{:?}", std::char::from_digit(10, 16)); // Some('a')
    

5. 元组类型

  • 元组(tuple)由多个各种类型的值组成,使用点(.)索引来访问元组中的内容。例如:
    let x:(&str, i32) = ("aa", 10);
    println!("x0 = {}, x1 = {}", x.0, x.1); // x0 = aa, x1 = 10
    fn split_at() -> (i32, &str);  // 元组作为返回值
    
    let str = "hello world";
    let re = str.split_at(5);
    println!("re.0 = {}, re.1 = {}", re.0, re.1); // re.0 = hello, re.1 =  world
  • 零元组 也被称为 基元类型(unit type),因为它只有一个值,写作 ()。 当不存在有意义的值而上下文又要要求某种类型时,Rust会使用这种基元类型。

  • 没有返回值的函数的返回类型就是 ()。

    fn swap<T>(x: &mut T, y: &mut T) {}  // 先定义一个函数
    let mut a = "10".to_string();
    let mut b = 20.to_string();
    let re = swap::<String>(&mut a, &mut b);
    println!("re = {:?}", re); // 此处输出为: re = ()