變量綁定與原生類型
變量綁定
Rust 通過 let 關鍵字進行變量綁定。
fn main() { let a1 = 5; let a2:i32 = 5; assert_eq!(a1, a2); //let 綁定 整數變量默認類型推斷是 i32 let b1:u32 = 5; //assert_eq!(a1, b1); //去掉上面的註釋會報錯,因為類型不匹配 //errer: mismatched types }
這裡的 assert_eq! 宏的作用是判斷兩個參數是不是相等的,但如果是兩個不匹配的類型,就算字面值相等也會報錯。
可變綁定
rust 在聲明變量時,在變量前面加入 mut 關鍵字,變量就會成為可變綁定的變量。
fn main() { let mut a: f64 = 1.0; let b = 2.0f32; //改變 a 的綁定 a = 2.0; println!("{:?}", a); //重新綁定為不可變 let a = a; //不能賦值 //a = 3.0; //類型不匹配 //assert_eq!(a, b); }
這裡的 b 變量,綁定了 2.0f32。這是 Rust 裡面值類型顯式標記的語法,規定為value+type的形式。
例如: 固定大小類型:
1u8 1i8
1u16 1i16
1u32 1i32
1u64 1i64
可變大小類型:
1usize 1isize
浮點類型:
1f32 1f64
let解構
為什麼在 Rust 裡面聲明一個變量的時候要採用 let 綁定表達式? 那是因為 let 綁定表達式的表達能力更強,而且 let 表達式實際上是一種模式匹配。
例如:
fn main() { let (a, mut b): (bool,bool) = (true, false); println!("a = {:?}, b = {:?}", a, b); //a 不可變綁定 //a = false; //b 可變綁定 b = true; assert_eq!(a, b); }
這裡使用了 bool,只有true和false兩個值,通常用來做邏輯判斷的類型。
原生類型
Rust內置的原生類型 (primitive types) 有以下幾類:
- 布爾類型:有兩個值true和false。
- 字符類型:表示單個Unicode字符,存儲為4個字節。
- 數值類型:分為有符號整數 (i8,i16,i32,i64,isize)、 無符號整數 (u8,u16,u32,u64,usize) 以及浮點數 (f32,f64)。
- 字符串類型:最底層的是不定長類型str,更常用的是字符串切片&str和heap分配字符串String, 其中字符串切片是靜態分配的,有固定的大小,並且不可變,而heap分配字符串是可變的。
- 數組:具有固定大小,並且元素都是同種類型,可表示為[T; N]。
- 切片:引用一個數組的部分數據並且不需要拷貝,可表示為&[T]。
- 元組:具有固定大小的有序列表,每個元素都有自己的類型,通過解構或者索引來獲得每個元素的值。
- 指針:最底層的是裸指針*const T和*mut T,但解引用它們是不安全的,必須放到unsafe塊裡。
- 函數:具有函數類型的變量實質上是一個函數指針。
- 元類型:即(),其唯一的值也是()。
#![allow(unused)] fn main() { // boolean type let t = true; let f: bool = false; // char type let c = 'c'; // numeric types let x = 42; let y: u32 = 123_456; let z: f64 = 1.23e+2; let zero = z.abs_sub(123.4); let bin = 0b1111_0000; let oct = 0o7320_1546; let hex = 0xf23a_b049; // string types let str = "Hello, world!"; let mut string = str.to_string(); // arrays and slices let a = [0, 1, 2, 3, 4]; let middle = &a[1..4]; let mut ten_zeros: [i64; 10] = [0; 10]; // tuples let tuple: (i32, &str) = (50, "hello"); let (fifty, _) = tuple; let hello = tuple.1; // raw pointers let x = 5; let raw = &x as *const i32; let points_at = unsafe { *raw }; // functions fn foo(x: i32) -> i32 { x } let bar: fn(i32) -> i32 = foo; }
有幾點是需要特別注意的:
- 數值類型可以使用_分隔符來增加可讀性。
- Rust還支持單字節字符b'H'以及單字節字符串b"Hello",僅限制於ASCII字符。 此外,還可以使用r#"..."#標記來表示原始字符串,不需要對特殊字符進行轉義。
- 使用&符號將String類型轉換成&str類型很廉價, 但是使用to_string()方法將&str轉換到String類型涉及到分配內存, 除非很有必要否則不要這麼做。
- 數組的長度是不可變的,動態的數組稱為Vec (vector),可以使用宏vec!創建。
- 元組可以使用==和!=運算符來判斷是否相同。
- 不多於32個元素的數組和不多於12個元素的元組在值傳遞時是自動複製的。
- Rust不提供原生類型之間的隱式轉換,只能使用as關鍵字顯式轉換。
- 可以使用type關鍵字定義某個類型的別名,並且應該採用駝峰命名法。
#![allow(unused)] fn main() { // explicit conversion let decimal = 65.4321_f32; let integer = decimal as u8; let character = integer as char; // type aliases type NanoSecond = u64; type Point = (u8, u8); }