系列文章目錄
【跟小嘉學(xué) Rust 編程】一、Rust 編程基礎(chǔ)
【跟小嘉學(xué) Rust 編程】二、Rust 包管理工具使用
【跟小嘉學(xué) Rust 編程】三、Rust 的基本程序概念
前言
本章節(jié)涵蓋幾乎所有編程語言會出現(xiàn)的概念以及他們在 Rust之中的工作原理,這不是 Rust 獨(dú)有的,但我們將在 Rust 上下文中討論他們,并且解釋這些概念。詳細(xì)來講就是變量、基本類型、函數(shù)、注釋和控制流。
主要教材參考 《The Rust Programming Language》
一、變量以及可變性
1.1、變量聲明語法
let [mut] variableName[:type] [= initialValue]
- 變量必須先聲明在使用
- rust 沒有默認(rèn)構(gòu)造函數(shù),變量沒有默認(rèn)值;
- variableName 以字母(unicode)、下劃線、數(shù)字組成,但是必須以字母(unicode)、下劃線開頭;
- 未聲明類型的為自動(dòng)類型推導(dǎo),但不意味著動(dòng)態(tài)類型。
1.2、不可變變量
默認(rèn)情況下,變量是不可變的,這是 Rust 提供的用于安全性和簡單并發(fā)性方式編寫代碼。
例子:不可變變量
fn main() {
let x = 5;
println!("The value of x is: {x}");
x = 6;
println!("The value of x is: {x}");
}
錯(cuò)誤提示
raojiamin@192 hello % cargo build
Compiling hello v0.1.0 (/Users/raojiamin/Desktop/code/rust_code/hello)
error[E0384]: cannot assign twice to immutable variable `x`
--> src/main.rs:4:5
|
2 | let x = 5;
| -
| |
| first assignment to `x`
| help: consider making this binding mutable: `mut x`
3 | println!("The value of x is: {x}");
4 | x = 6;
| ^^^^^ cannot assign twice to immutable variable
For more information about this error, try `rustc --explain E0384`.
error: could not compile `hello` (bin "hello") due to previous error
初始化本身可以依賴變量,可能多次調(diào)用它所在函數(shù)可能得到不同的值;
1.3、未使用變量警告
如果你聲明了變量但是并未使用,編譯器則會給你一個(gè)變量未使用的警告。
warning: unused variable: `x`
--> src/main.rs:2:9
|
2 | let x = 5;
| ^ help: if this is intentional, prefix it with an underscore: `_x`
|
= note: `#[warn(unused_variables)]` on by default
warning: `hello` (bin "hello") generated 1 warning (run `cargo fix --bin "hello"` to apply 1 suggestion)
Finished dev [unoptimized + debuginfo] target(s) in 0.89s
1.4、使用 let mut 可變變量
fn main() {
let mut y = 100;
// help: maybe it is overwritten before being read?rustc(unused_assignments)
// 如果在第二次賦值前沒有讀取該變量會有上述警告
println!("the y value is {}", y);
y = 100;
println!("the y value is {}", y);
}
1.5、使用 const 聲明常量
初始化過程完全靜態(tài)(編譯器時(shí)期已知其值),且不會改變。
fn main() {
const X:i32 = 100;
// warning: constant is never used: `x` 警告:常量必須被使用
// warning: constant `x` should have an upper case name 常量必須大寫
// error: missing type for `const` item 錯(cuò)誤:常量必須聲明類型
println!("the X value is {}", X);
}
const 常量一定不能 使用 mut 修飾。
1.6、Shadowing
該特性可以反復(fù)聲明不可變對象,她可以重新更改不可變變量的數(shù)據(jù)類型,該語法特性一般用于中間變量。
fn main() {
let x = 5;
let x = x + 1;
let x = x * 2;
println!("The value of x is: {}", x);
}
該特性不允許使用在可變對象上。
fn main() {
let mut spaces = " ";
spaces = spaces.len();
}
錯(cuò)誤提示
cargo build
Compiling hello v0.1.0 (/Users/raojiamin/Desktop/code/rust_code/hello)
error[E0308]: mismatched types
--> src/main.rs:3:14
|
2 | let mut spaces = " ";
| ----- expected due to this value
3 | spaces = spaces.len();
| ^^^^^^^^^^^^ expected `&str`, found `usize`
|
help: try removing the method call
|
3 - spaces = spaces.len();
3 + spaces = spaces;
|
For more information about this error, try `rustc --explain E0308`.
error: could not compile `hello` (bin "hello") due to previous error
1.7、暫時(shí)不使用的變量
fn main() {
let _ = "hello";
let _num = 100; // 表示可暫時(shí)不使用該變量
println!("{}", _); // 編譯錯(cuò)誤!“_” 的含義是忽略該變量綁定,之后不會再用了
}
以下劃線開頭的變量名,如 ”_num“, 表示可以暫時(shí)不使用該變量;
1.8、全局常量和全局靜態(tài)變量
在Rust 之中沒有全局變量的概念,但是可以使用全局靜態(tài)變量和全局常量。
1.8.1、全局常量
- 全局常量必須在聲明的時(shí)候初始化;
- 全局常量名必須大寫
- 全局常量必須在聲明的時(shí)候顯示聲明類型;
1.8.2、全局常量
- 靜態(tài)變量必須在聲明時(shí)初始化;
- 靜態(tài)變量必須編譯時(shí)可確定的常量, 變量名必須大寫;
- mut 修飾的靜態(tài)變量,使用的時(shí)候必須 unsafe 函數(shù)或者 unsafe 代碼塊;
- 靜態(tài)變量在聲明時(shí)候必須指定靜態(tài)的變量的數(shù)據(jù)類型;
二、數(shù)據(jù)類型
2.1、標(biāo)量類型(Scalar Types)
標(biāo)量類型表示單個(gè)值。Rust 中有四種主要的標(biāo)量類型:整型、浮點(diǎn)型、布爾類型、字符。
2.1.1、整型(Integer Types)
2.1.1.1、幾種整型類型
整型數(shù)據(jù)默認(rèn)是 i32 類型, isize 或 usize 在 32 位機(jī)器上就是 4 個(gè)字節(jié),在 64 位機(jī)器上就是 8 個(gè)字節(jié)。
Length | Signed | Unsigned| |
---|---|---|
8-bit | i8 | u8 |
16-bit | i16 | u16 |
32-bit | i32 | u32 |
64-bit | i64 | u64 |
128-bit | i128 | u128 |
arch | isize | usize |
每一個(gè)變量都可以是有符號或無符號,并且具有明確的大小,有符號數(shù)使用二進(jìn)制補(bǔ)碼來表示存儲。(早期8086 cpu只支持加法指令)
- 原碼:最高位為符號位,0代表正數(shù),1代表負(fù)數(shù),其余各位為數(shù)值本身的絕對值
- 反碼:
- 正數(shù):反碼與原碼相同,這是規(guī)定;
- 負(fù)數(shù):符號位為1不變,其余位對原碼取反;
- 補(bǔ)碼:
- 正數(shù):補(bǔ)碼與原碼相同
- 負(fù)數(shù):符號位為1不變,其余位對原碼取反加1;
isize 和 usize的主要場景是對某種集合進(jìn)行索引操作。
2.1.1.2、整型字面量(Integer Literals)
Number literals | Example | |
---|---|
Decimal | 98_222 |
Hex | 0xff |
Octal | 0o77 |
Binary | 0b1111_000 |
Byte(u8 only) | b’a’ |
除了byte類型外,所有數(shù)值字面量都允許使用類型后綴,例如:67u8;
2.1.1.3、整數(shù)溢出
u8的范圍是0-255,如果你把一個(gè) u8的值設(shè)置為 256。
- 調(diào)試模式(Debug)下,rust 會檢查整數(shù)溢出,如果發(fā)生溢出,程序會在運(yùn)行時(shí)就會 panic。
- 發(fā)布模式(Release)下,rust 不會檢查整數(shù)溢出,若果發(fā)生溢出,rust 會執(zhí)行環(huán)繞操作,不會拋出 panic;
如果要在 release 模式下打開整數(shù)溢出檢查后,只需要在 Cargo.toml 中配置
[profile.release]
overflow-checks = true
2.1.2、浮點(diǎn)型(Floating-Point Types)
浮點(diǎn)數(shù)有兩種類型:f32(單精度)、f64(雙精度)。Rust的浮點(diǎn)類型使用了 IEEE-754 標(biāo)準(zhǔn)來表述。 f64 是默認(rèn)類型,因?yàn)樵诂F(xiàn)代 CPU 上 f64 和 f32 的速度差不多,而且精度更高。
2.1.3、布爾類型(Boolean Type)
布爾類型只有兩個(gè)值:true、false。布爾類型的大小為1 字節(jié),在 rust 中 布爾類型使用 bool 關(guān)鍵字。
2.1.4、字符(Character Type)
字符類型是一個(gè)比較特別的,在 Java 和 CPP 之中 都只占用 1個(gè)字節(jié),但是 Rust 為了支持描述任何一個(gè) unicode 字符, char 類型需要 4個(gè)字節(jié)來描述,這樣會帶來空間資源的浪費(fèi),因?yàn)?ASCII 字符其實(shí)只需要 1 個(gè)字節(jié)的空間。如果只需要單字節(jié)即可,Rust 給出的解決方案是用 ‘b’ 來聲明單字節(jié),將字符以u8類型的形式存儲。
let x: u8 = b'A'; // 占 1 個(gè)字節(jié)
let y: char = 'A'; // 占 4 個(gè)字節(jié)
2.1.5、數(shù)字操作
Rust 支持所有數(shù)字類型所需要的基本數(shù)學(xué)操作:+、-、*、/、% 。 整數(shù)觸發(fā)會向零截?cái)嗟阶罱咏恼麛?shù)。
fn main() {
// addition
let sum = 5 + 10;
// subtraction
let difference = 95.5 - 4.3;
// multiplication
let product = 4 * 30;
// division
let quotient = 56.7 / 32.2;
let truncated = -5 / 3; // Results in -1
// remainder
let remainder = 43 % 5;
}
2.2、復(fù)合類型(Compound Types)
復(fù)合類型可以將多個(gè)值分組到一個(gè)類型中,Rust 中有兩種基本復(fù)合類型:元組和數(shù)組。
2.2.1、元組(Tuple Type)
元組是一個(gè)具有多種數(shù)據(jù)類型的多個(gè)值組合成一個(gè)復(fù)合類型,元組有固有的長度。一旦聲明它們的長度就不會增長或縮小。
2.2.1.1、元組定義
我們通常在括號內(nèi)寫一個(gè)逗號分隔的值列表來創(chuàng)建元組。
fn main() {
let tup:(i32, f64, u8) = (500, 6.4, 1);
// 定義空元組
let tup01:() = ();
// 單個(gè)元素元組
let tup02 = (1,);
println!("{:?}", tup01);
println!("{:?}", tup02);
println!("{:?}", tup);
}
需要注意:
- 如果你使用顯示數(shù)據(jù)類型聲明單個(gè)元素的元組,編譯器會給出警告;
- 如果你要聲明單個(gè)元素,必須使用自動(dòng)類型推斷,并且初始化的時(shí)候必須帶有逗號,否則會被編譯器認(rèn)為是單個(gè)元素變量;
2.2.1.2、訪問元組的方式
2.2.1.2.1、模式解構(gòu)
fn main() {
let tup:(i32, f64, u8) = (500, 6.4, 1);
let (x, y, z) = tup;
println!("{:?}", tup);
println!(" the value of x is :{}", x);
println!(" the value of y is :{}", y);
println!(" the value of z is :{}", z);
}
2.2.1.2.2、數(shù)字索引(使用.
來訪問元組)
模式解構(gòu)可以讓我們一次性把元組全部獲取出來,如果我們想要訪問某個(gè)元組, 可以使用 . 操作符來訪問;和其他語言一樣 數(shù)組、字符串、元組的索引從0開始。
fn main() {
let x: (i32, f64, u8) = (500, 6.4, 1);
let five_hundred = x.0;
let six_point_four = x.1;
// 如果索引不在范圍內(nèi),會報(bào)如下錯(cuò)誤 error[E0609]: no field `3` on type `(i32, f64, u8)`
println!("five_hundred is {}", five_hundred);
println!("six_point_four is {}", six_point_four);
}
2.2.2、數(shù)組(Array Type)
數(shù)組的每個(gè)元素都必須具有相同的類型,數(shù)組具有固定的長度,依次線性排列。
2.2.2.1、數(shù)組的定義
數(shù)組的定義格式如下:let 變量名[類型; 數(shù)組長度] = [初始化列表];
fn main() {
let array:[i32; 3] = [1,3,5];
let months = ["January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"];
// 如果一個(gè)數(shù)組有多個(gè)重復(fù)的元素的時(shí)候
let a = [3;5];
println!("array: {:?}", array);
println!("months: {:?}", months);
}
2.2.2.2、數(shù)組的訪問
使用索引訪問數(shù)組的元素,索引從0開始,到數(shù)組長度-1;如果超出數(shù)組索引訪問將會運(yùn)行時(shí)報(bào)錯(cuò)。
fn main() {
let a = [9, 8, 7, 6, 5];
let first = a[0]; // 獲取a數(shù)組第一個(gè)元素
let second = a[1]; // 獲取第二個(gè)元素
println!("first: {:?}", first);
println!("second: {:?}", second);
}
索引越界的時(shí)候,程序?qū)?zhí)行錯(cuò)誤
error: this operation will panic at runtime
--> src/main.rs:5:18
|
5 | let second = a[6]; // 獲取第二個(gè)元素
| ^^^^ index out of bounds: the length is 5 but the index is 6
|
= note: `#[deny(unconditional_panic)]` on by default
error: could not compile `hello` (bin "hello") due to previous error
三、函數(shù)
函數(shù)在Rust代碼只能夠很常見,我們已經(jīng)見到了最重要的函數(shù) main 函數(shù),他是許多程序的入口函數(shù),我們還看到了 fn 關(guān)鍵字。
3.1、函數(shù)定義
在 rust 里面函數(shù)使用 fn 關(guān)鍵字聲明。rust中函數(shù)名采用所有字母都是小寫的,并且使用下劃線分隔單詞。函數(shù)使用大括號包括起來。
// 無參函數(shù)
fn another_function() {
println!("Another function.");
}
3.2、函數(shù)參數(shù)(parameters)
// 函數(shù)參數(shù),函數(shù)的參數(shù)必須聲明參數(shù)的類型
fn another_function(x: i32) {
println!("Another function.");
}
- 定義函數(shù)的時(shí)候聲明的參數(shù)叫做形式參數(shù);
- 調(diào)用函數(shù)的時(shí)候傳入的參數(shù)叫做實(shí)際參數(shù);
3.3、返回值(Return Values)
// 函數(shù)返回值
fn five() -> i32 {
println!("Another function.");
return 5; //或者直接寫 5
}
在 rust 里面,函數(shù)可以在函數(shù)里面定義,也可以在函數(shù)外面定義。
函數(shù)里包含了語句和表達(dá)式。在rust語言里面。函數(shù)定義也是語句,所以函數(shù)可以在函數(shù)內(nèi)部定義。
需要注意的是我們在省略 return 關(guān)鍵字的時(shí)候,不能帶有分號,否則會報(bào)錯(cuò)
error[E0308]: mismatched types
--> src/main.rs:7:24
|
7 | fn plus_one(x: i32) -> i32 {
| -------- ^^^ expected `i32`, found `()`
| |
| implicitly returns `()` as its body has no tail or `return` expression
8 | x + 1;
| - help: remove this semicolon to return this value
3.4、語句和表達(dá)式(Statements and Expressions)
函數(shù)體是由一些語句組成,可選地以表達(dá)式結(jié)尾。
3.4.1、語句
執(zhí)行某些操作但不返回值的指令
3.4.1.1、賦值語句
let y = 6;
let 語句不能作為賦值語句的右值。
3.4.1.2、代碼塊
fn main() {
let y = {
let x = 3;
x + 1
};
println!("The value of y is: {y}");
}
3.4.2、表達(dá)式
表達(dá)式求值為結(jié)果值。
四、注釋(Comments)
所有程序員都努力使它們的代碼易于理解,但是有時(shí)候額外的解釋是必要的,編譯器會忽略這些注釋。
五、控制流(Control Flow)
5.1、if 表達(dá)式
if 表達(dá)式 允許根據(jù)條件對代碼進(jìn)行分支選擇,如果條件滿足,則運(yùn)行,否則不運(yùn)行。
if 后面必須得更 bool 類型變量或表達(dá)式,否則將會報(bào)錯(cuò)
error[E0308]: mismatched types
--> src/main.rs:4:8
|
4 | if number {
| ^^^^^^ expected `bool`, found integer
5.1.1、if else 表達(dá)式
1、雙分支結(jié)構(gòu)
fn main() {
let number = 3;
if number < 5 {
println!("condition was true");
} else {
println!("condition was false");
}
}
2、多分枝結(jié)構(gòu)
fn main() {
let number = 6;
if number % 4 == 0 {
println!("number is divisible by 4");
} else if number % 3 == 0 {
println!("number is divisible by 3");
} else if number % 2 == 0 {
println!("number is divisible by 2");
} else {
println!("number is not divisible by 4, 3, or 2");
}
}
5.1.2、在let語句中使用 if
在 let 語句右邊可以使用 if 表達(dá)式,但是要求兩個(gè)分支的值要是相同的類型,否則將會報(bào)錯(cuò)
fn main() {
let condition = true;
let number = if condition { 5 } else { 6 };
println!("The value of number is: {number}");
}
5.2、循環(huán)(loops)
5.2.1、loop 循環(huán)
5.2.1.1、loop 死循環(huán)
fn main() {
loop {
println!("again!");
}
}
5.2.1.2、loop 循環(huán)返回值
fn main() {
let mut counter = 0;
let result = loop {
counter += 1;
if counter == 10 {
break counter * 2;
}
};
println!("The result is {result}");
}
5.2.1.2、loop 標(biāo)簽結(jié)合break 來跳出指定循環(huán)
fn main() {
let mut count = 0;
'counting_up: loop {
println!("count = {count}");
let mut remaining = 10;
loop {
println!("remaining = {remaining}");
if remaining == 9 {
break;
}
if count == 2 {
break 'counting_up;
}
remaining -= 1;
}
count += 1;
}
println!("End count = {count}");
}
5.2.2、while 循環(huán)
5.2.2.1、while 循環(huán)
fn main() {
let mut number = 3;
while number != 0 {
println!("{number}!");
number -= 1;
}
println!("LIFTOFF!!!");
}
5.2.2.2、使用 while 循環(huán)遍歷數(shù)組
fn main() {
let a = [10, 20, 30, 40, 50];
let mut index = 0;
while index < 5 {
println!("the value is: {}", a[index]);
index += 1;
}
}
5.2.3、for 循環(huán)
5.2.3.1、遍歷序列
fn main() {
for i in 1..11 {
println!("{}", i);
}
}
其中 1…11 是 Range 對象的定義形式,表示的是1-10 的序列;文章來源:http://www.zghlxwxcb.cn/news/detail-495918.html
fn main() {
for number in (1..4).rev() {
println!("{number}!");
}
println!("LIFTOFF!!!");
}
5.2.3.2、迭代器循環(huán)
fn main(){
let fruits=["mango","apple","banana","litchi","watermelon"];
for fruit in fruits.iter()
{
print!("{:?} ",fruit);
}
}
5.2.3.3、數(shù)組遍歷
fn main() {
let a = [10, 20, 30, 40, 50];
for element in a {
println!("the value is: {element}");
}
}
總結(jié)
以上就是今天要講的內(nèi)容文章來源地址http://www.zghlxwxcb.cn/news/detail-495918.html
- 本文介紹了 Rust 基本程序概念,主要包含 Rust 變量和常量的定義使用、Rust 數(shù)據(jù)類型、Rust 流程控制;
到了這里,關(guān)于【跟小嘉學(xué) Rust 編程】三、Rust 的基本程序概念的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!