类型
rust提供了几种机制来实现基本类型和用户自定义类型的转换和定义。
原始类型之间的转换
rust中没有提供基本类型之间隐式地类型的转换。
但是,我们可以通过as
关键字来进行显示类型的转换。
在rust中,数字类型的转换和C语言中的转换一样,除了C语言中的未定义的行为。整数类型之间的所有转换情况都已经在Rust中定义好了。
// 禁止类型转中的类型溢出警告
#![allow(overflowing_literals)]
fn main(){
let decimal = 65.4321_f32;
// 编译器会报错,没有隐式类型转换
let integer: u8 = decimal;
// 显示类型转换
let integer = decimal as u8;
let character = integer as char;
// 编译器会报错,浮点数无法直接转换成字符类型
let character = decimal as character;
println!("Casting: {} -> {} -> {}", decimal, integer, character);
// 有符号数转换为无符号数
// 在没有发生类型溢出时,数字是原样转换
// 如果有类型溢出或者符号,则按照C的规则处理
println!("1000 as a u8 is : {}", 1000 as u16);
println!("-1 as a u8 is : {}", (-1i8) as u8);
println!("128 as a i16 is : {}", 128 as i16);
println!("128 as a i8 is : {}", 128 as i8);
println!("1000 as a u8 is : {}", 1000 as u8);
println!("232 as a i8 is : {}", 232 as i8);
}
指定字面量的类型
数值型字面量通过把类型名称以后缀的形式添加到变量名中来实现类型的注解。例如,为了指出字面量42
应该有的类型i32
,我们应该写作42i32
。
没有类型后缀的数字字面量的类型依赖于它后续怎么被使用的。
如果没有限制存在,编译器将会把整数的类型设置为i32
,浮点数的类型设置为f64
。
fn main(){
// 被后缀修饰的字面量,他们的类型在初始化的时候是已知的。
let x = 1u8;
let y = 2u32;
let z = 3f32;
let i = 1;
let f = 1.0;
println!("size of `x` in bytes: {}", std::mem::size_of_val(&x));
println!("size of `y` in bytes: {}", std::mem::size_of_val(&y));
println!("size of `z` in bytes: {}", std::mem::size_of_val(&z));
println!("size of `i` in bytes: {}", std::mem::size_of_val(&i));
println!("size of `f` in bytes: {}", std::mem::size_of_val(&f));
}
使用类型推断
类型引擎推断非常智能。该引擎所做的远比在初始化时检查值表达式的类型所做的多。为了推断它的类型,该引擎会检查在这之后该变量是如何使用的。
fn main(){
let elem = 5u8;
// 创建一个空的向量,此时编译器不知道该向量的类型
let mut vec = Vec::new();
// 通过push调用推断出来向量的类型是Vec<u8>。
vec.push(elem);
println!("{:?}", vec);
}
类型别名
可以使用type
关键字来给已存在的类型一个新的名称。
类型的名称必须是大驼峰的形式,否则编译器会发出告警。
这个规则的例外是原始类型:usize
、f32
。
type NanoSecond = u64;
type Inch = u64;
#[allow(non_camel_case_types)]
type u64_t = u64;
fn main(){
let nanoseconds: NanoSecond = 5 as u64_t;
let inches: Inch = 2 as u64_t;
println!("{} nanoseconds + {} inches = {} unit ?",
nanoseconds,
inches,
nanoseconds + inches
);
}