Rust: 基础类型补充

在上一篇中,我们介绍了 Rust 基础类型的相关内容,限于篇幅,有些内容没有覆盖到,今天就来做个补充。

一、数字类型字面量

在声明数字类型字面量时,Rust 提供了 类型后缀 的表示方法,只需要在数字后面加上对应的类型即可,另外,Rust 也允许在数字中加入 下划线 符号,可以用来间隔值和类型,也可以用来表示千分位,这个特性大大增强了程序的可读性。

下面我们来演示一下:

// 引入标准库mem模块
use std::mem;

fn main() {
    // 带后缀的字面量
    let a = 1u8;
    let b = 2u32;
    let c = 3i64;
    // 下划线间隔值和类型
    let d = 4_f32;
    // 下划线表示千分位
    let e = 5_000.000_1;
    
    // 求出占用的字节数
    let a_bytes = mem::size_of_val(&a);
    let b_bytes = mem::size_of_val(&b);
    let c_bytes = mem::size_of_val(&c);
    let d_bytes = mem::size_of_val(&d);
    let e_bytes = mem::size_of_val(&e);
    
    println!("a: {} bytes", a_bytes);
    println!("b: {} bytes", b_bytes);
    println!("c: {} bytes", c_bytes);
    println!("d: {} bytes", d_bytes);
    println!("e: {} bytes", e_bytes);
}

可以看到在上面代码中,我们引入了标准库的 mem 模块,利用该模块的 size_of_val() 方法,能够获取到每个数据类型在内存中占用的字节数。

运行代码,打印结果如下:

a: 1 bytes
b: 4 bytes
c: 8 bytes
d: 4 bytes
e: 8 bytes

二、类型别名

Rust 允许我们为类型定义一个别名,在后续的代码中都可以使用这个别名:

// 类型别名强制大驼峰式命名
type Int = i32;
type Long = i64;
type Double = f64;
type Array = [i32; 5];

fn main() {
    // 使用类型别名
    let a: Int = 1;
    let b: Long = 2;
    let c: Double = 3.0;

    println!("{} {} {}", a, b, c);

    // 使用类型别名
    let ary: Array = [1, 2, 3, 4, 5];
    
    println!("{:?}", ary);
}

正如代码注释所示,Rust 强制别名使用大驼峰式风格,即首字母大写。如果我们不习惯这样的风格,则须为别名加上一个属性说明:

// 每个别名都须加上该属性
#[allow(non_camel_case_types)]
type int = i32;

#[allow(non_camel_case_types)]
type long = i64;

fn main() {
    let a: int = 1;
    let b: long = 2;

    println!("{} {}", a, b);
}

三、类型转换

Rust 规定,类型之间须使用 as 关键字进行显式转换。不过,数字和字符串之间互转略有不同,我们且看下面介绍。

1. 布尔类型转数字

布尔类型可以转换为任意的数字类型,结果将会是 0 或 1。但反之却不行,Rust 不允许数字类型向布尔类型转换。

下面是布尔类型转数字的过程:

fn main() {
    let number = false as u8;
    
    // 打印结果 0
    println!("{:?}", number);
    
    let number = true as i32;
    
    // 打印结果 1
    println!("{:?}", number);
}

2. 数字之间互转

前面我们介绍过,数字分为很多种不同的类型,它们之间是可以相互转换的:

fn main() {
    // 默认f64类型浮点数
    let decimal = 65.0;
    
    // 转为u8类型
    let integer = decimal as u8;
    
    // 打印结果 65
    println!("{:?}", integer);
    
    // 转为f32浮点数
    let decimal = integer as f32;
    
    // 打印结果 65.0
    println!("{:?}", decimal);
}

特别要注意的是,如果在转换时,数字超出了目标类型的表示范围,则会出现溢出现象(如果以 debug 模式编译,超出范围时则会引起一个 panic 异常,这一点有所不同):

fn main() {
    // 超出u8范围的i32数字
    let origin = 256;
    
    // 将会出现溢出
    let result = origin as u8;
    
    // 打印结果 0
    println!("{}", result);
}

3. 数字和字符之间互转

每个字符都有与之对应的数字,所以字符可以转为数字。反过来,数字也可以转为字符,但要注意的是,Rust 规定只有 u8 数字类型可以转为 char 类型。

数字和字符之间的转换代码如下:

fn main() {
    // ASCII字符
    let character = 'a';
    
    // 转为u8类型数字
    let number = character as u8;
    
    // 打印结果 97
    println!("{}", number);
    
    // 中文字符
    let character = '中';
    
    // char转为i32
    let number = character as i32;
    
    // 打印结果 20013
    println!("{}", number);
    
    // 只有u8类型可以转为char类型
    let number = 65u8;
    
    // u8数字转为字符
    let character = number as char;
    
    // 打印结果 'A'
    println!("{:?}", character);
}

4. 数字与字符串之间互转

数字与字符串之间的转换,使用频率非常高,下面我们通过两段代码,来演示一下转换的过程:

数字转字符串:

fn main() {
    let number = 5;
    
    // i32转为String
    let string = number.to_string();
    
    // 打印结果 "5"
    println!("{:?}", string);
}

字符串转数字:

fn main() {
    // &str类型
    let s = "3";

    // parse()时指定目标类型
    let n = s.parse::<i32>().unwrap();
    
    // 打印结果 3
    println!("{:?}", n);
    
    // String类型
    let s = String::from("5");
    
    // 声明变量时 指定目标类型
    let n: i32 = s.parse().unwrap();
    
    // 打印结果 5
    println!("{:?}", n);
}

以上就是类型相关的补充内容了,如果仍有未涉及到的细节,我们后续再做介绍。

原文地址:https://www.cnblogs.com/liuhe688/p/13416091.html