本篇文章包含的內容
- 1 變量與常量
- 2 類型
- 2.1 標量類型
- 2.2 復合類型
- 3 函數
- 4 控制流
- 4.1 分支
- 4.2 循環
1 變量與常量
在Rust中,使用let
關鍵字聲明一個變量,變量默認是不可變的。如果要聲明可變變量,需要使用mut
關鍵字將其聲明為可變變量。
let x = 1;
x = 2; // 默認不可變,非法
let x = 2; // shadow,合法let mut y = 1;
y = 2;
聲明常量需要使用const
關鍵字,并且在聲明時必須指明類型。它甚至可以聲明在全局部位,命名需要滿足一定的規則:字母全部大寫,單詞之間用下劃線隔開。
const MAX_POINT : u32 = 100_000;
常量一定是不可變的,所以不需要mut
關鍵字聲明,但是它與默認不可變的let
聲明的變量有區別。它的賦值結果只能是常量表達式,不能是函數的返回值或者運行時才可以獲得的值。
shadowing(隱藏)是Rust的一個重要特性,它允許新聲明的變量的變量名替代舊變量。這在很大程度上提高了程序的可讀性。被shadow前后的變量類型可以不同。
let spaces = " "; // str
let spaces = spaces.len(); // usize,這里返回 4
2 類型
2.1 標量類型
Rust中有四種標量類型(老四樣):
- 整數:默認
i32
; - 浮點:默認
f64
; - 布爾:只有兩個值,
true
和false
,占一個字節。 - 字符:Unicode標量值,占用4個字節,可以表示中日韓字符,emoji表情等。
整數類型具體可由下表表示。其中isize
和usize
由操作系統決定,如果操作系統是64位,則isize
相當于i64
,usize
相當于u64
。
整數的表示與C/C++類似,甚至可以添加下劃線以提高可讀性。例如10_0000
、0xA0
、0b1100_0011
、甚至可以表示為byte類型(u8
only):b'A'
。除了byte類型外,其他整數都可以使用類型后綴,例如57u8
。如果整數溢出,Rust僅會在debug編譯模式下panic(恐慌),而在release版本中程序不會panic。
2.2 復合類型
Rust語言中有兩種基礎的復合類型,即元組(Tuple)和數組。元組用小括號表示,數組用中括號表示。元組中的每一個元素可以是不同類型,而數組中的所有元素都必須是同一種類型。無論是元組還是數組,都需要顯式聲明他們的類型。
下面是一個使用元組的例子,可以臨時聲明一個新的元組,例如(x, y, z)
來結構獲取舊元組中的每一個成員(Rust會自動推斷x
、y
、z
的類型)。
fn main() {let tup : (i32, i64, u8) = (1, 2, 3);let (x, y, z) = tup; // destructureprintln!("{}, {}, {}", x, y, z);println!("{}, {}, {}", tup.0, tup.1, tup.2)
}
使用下面的方法定義一個數組,可以顯式地制定數組元素的類型,也可以讓Rust編譯器自動推斷所需的數組類型。如果訪問的數組索引超出了數組的范圍,編譯可能不會報錯,但是運行時會導致程序panic。
fn main() {let a = [1, 2, 3, 4 , 5];let b: [i32; 5] = [1, 2, 3, 4, 5];let mouths = ["January","February","March","April","May","June","July","August","September","October","November","December"];let arr = [1; 3]; // let arr = [1, 1, 1];println!("{} {}", a[0], b[1]);
}
如果想讓數據存放在stack(棧)內存而不是heap(堆)內存上,或者想要保證有固定數量的元素,則可以使用數組。數組是Stack上分配的單個塊的內存。數組是定長的,而與之對應可變長度的數組稱為Vector(向量)。如果在實際編程中不知道需要使用數組還是Vector,那么一般都需要使用Vector。
3 函數
Rust函數的命名規范采用snake_case規范,即全部小寫,單詞之間用下劃線分開。Rust中的函數定義順序無需尊循C/C++的習慣,即函數必須先聲明再使用,在Rust中,可以將函數的定義放在函數使用之后。函數參數的類型必須指明。
fn main() {another_func(3);
}fn another_func(num: i32) {println!("Another function!");println!("the num is {}", num)
}
Rust是一個基于表達式的語言。任何一個函數體(語句塊,由花括號括起)都由一系列語句組成,可選地,可以由一個表達式結束,函數的返回值就是表達式的值(表達式會產生一個計算值)。
與表達式對應的概念稱為語句,一個語句相當于一個命令,語句沒有返回值(它返回一個空的Tuple)。函數的定義也是一個語句,所以它不能當作值賦值給變量(廢話),這一點和C/C++有很大不同(筆者認為相當于修復了C/C++的一個bug?)。函數的定義是語句,但是調用函數(宏)是一個表達式。
let x = (let y = 6); // 非法let y = {let x = 1;x + 2 // 不能加分號
};println!("the value of y is {}", y); // 3
對于需要返回值的函數,在->
符號后聲明函數返回值的類型,但是不能為返回值命名。在Rust中,函數的返回值就是函數最后一個表達式的值,如果需要提前返回,則可以使用 return
關鍵字,并指定一個值。
fn main() {let x = add_five(4);println!("{}", x); // 9
}fn add_five(num: i32) -> i32 {num + 5// return num + 5;
}
4 控制流
4.1 分支
if
表達式后需要添加一個條件,條件必須是bool類型(它不能是一個語句,這一點也與C/C++不同),與if相關聯的代碼稱為分支(arm)。當程序中出現多個else if
,則建議只用match
語句重構代碼。
fn main() {let x = 3;if x % 2 == 0 {println!("x can be devived by 2");} else if x % 3 == 0 {println!("x can be devived by 3");} else if x % 4 == 0 {println!("x can be devived by 4")}
}
if
是一個表達式,所以它可以放在賦值號的右邊。實現類似 ? : ;
的效果。需要特別注意的是,if
和else
后程序塊的返回值的類型必須相同。
let condition = true;let number = if condition { 5 } else { 6 }; // 5
4.2 循環
Rust中有三種循環:loop
、while
和for
。其使用方法與C/C++和Python比較類似,但是Rust也提供了一些其他的語法糖。
loop
表達式中可以使用break
語句打斷循環,并且break
語句后可以添加表達式的值來指定loop
表達式的返回值:
fn main() {let mut counter = 0;let result = loop {counter += 1;if counter == 10 {break counter * 2;}};println!("result: {}", result); // 20
}
while
循環使用較為簡單,這里不贅述。
遍歷集合元素一般使用for
。Rust中同樣存在迭代器的概念。注意,下面的例子中迭代器返回的是數組a
的引用,如果直接寫for element in a
,則element
將會被推斷為i32類型,而不是&i32
:
fn main() {let a = [1, 2, 3, 4, 5];for element in a.iter() {println!("the value is {}", element);}
}
如果需要代碼執行確定的次數,可以使用標準庫提供的Range
。Range
可以通過開始數字和結束數字生成一個范圍,但不包含結束數字。可以使用rev()
方法獲得反轉的Range
。
fn main() {for number in (1..4).rev() {println!("{}!", number);}println!("LIFTOFF!");
}
??原創筆記,碼字不易,歡迎點贊,收藏~ 如有謬誤敬請在評論區不吝告知,感激不盡!博主將持續更新有關嵌入式開發、FPGA方面的學習筆記。