iT邦幫忙

2022 iThome 鐵人賽

DAY 2
0
自我挑戰組

嘗試30天學「不」會Rust系列 第 2

[Rust] 變數與基本型別

  • 分享至 

  • xImage
  •  

環境

OS: Windows 10
Editor: Visual Studio Code
Rust version: 1.63.0

概述

認識一門新的程式語言,必免不了幾個步驟,今天來試著理解Rust中:

  1. 如何宣告變數
  2. 基礎型別(Primitive type)的限制
  3. 基礎型別的轉型

變數與常數

宣告

在Rust中宣告一個變數:

let x = 100;

這在近年熱門的的程式語言中都有類似的寫法或是語法糖,由編譯器去判斷型別是甚麼,其他與類似的寫法:

// C++
auto x = 100;

// C#
var x = 100;

// Golang
var x = 100

在沒有特定指定型別的情況下,通常會被判定為Int32,在這裡我想知道,let x = 100是不是真的是Int32,於是開始找看看有沒有內建的函式,可以幫我告訴我型別,後來看到了一個有趣的!

我們可以刻意寫一個error讓Rust compiler告訴我們型別是甚麼,於是:

let x = 100;
x.what_is_this_type(); // 這是為了讓compiler故意丟error回來

然後compiler告訴我:

Compiling basic v0.1.0 (D:\projects\rust_learning\basic)
error[E0599]: no method named `what_is_this_type` found for type `{integer}` in the current scope
 --> src\main.rs:3:7
  |
3 |     x.what_is_this_type();
  |       ^^^^^^^^^^^^^^^^^ method not found in `{integer}`

For more information about this error, try `rustc --explain E0599`.
error: could not compile `basic` due to previous error

知道是integar了,但是幾位元的,在這裡找到了答案,在Summary的地方。

 Integer literals whose type is unconstrained will default to i32

當然!我們也可以在宣告的時候,指定型別:

let x: u8 = 100;

然後一樣讓compiler告訴我們這個型別

Compiling basic v0.1.0 (D:\projects\rust_learning\basic)
error[E0599]: no method named `what_is_this_type` found for type `u8` in the current scope
 --> src\main.rs:3:7
  |
3 |     x.what_is_this_type();
  |       ^^^^^^^^^^^^^^^^^ method not found in `u8`

For more information about this error, try `rustc --explain E0599`.

嗯!確定是UInt8!

加法

再來就是常見的例子:

let x = 100;
x += 50;
println!("x is {}", x);

編譯!

 Compiling basic v0.1.0 (D:\projects\rust_learning\basic)
error[E0384]: cannot assign twice to immutable variable `x`
 --> src\main.rs:3:5
  |
2 |     let x = 100;
  |         -
  |         |
  |         first assignment to `x`
  |         help: consider making this binding mutable: `mut x`
3 |     x += 50;
  |     ^^^^^^^ cannot assign twice to immutable variable

For more information about this error, try `rustc --explain E0384`.

然後compiler丟了錯誤給我....(哭)

這個就是Rust跟其他語言一開始就不太一樣的地方了,let x的話這個變數是不可變的,如果要讓上面的範例可以成功編譯的話需要加上mut

let mut x = 100;
x += 50;
println!("x is {}", x);

常數

上面的例子讓我想知道一件事:那不可變數常數有甚麼差別呢?找了一些文件,這邊寫到:

首先,你無法在使用常數使用 mut,常數不是預設不可變,它們永遠都不可變。如果你使用 const 宣告而非 let 的話,你必須指明型別。

也就是說如果要宣告常,需要這樣:

const const_x: u8 = 100;

但這會丟Warning給你,要求你改成大寫:

const CONST_X: u8 = 100;

PS: 沒記錯的話,在Golang常數用小寫會直接丟error。

額外!

官方教學的這個小節告訴了我們一件事!

如果我們這樣宣告,那這樣寫會發生甚麼事呢?

let mut spaces = "   ";
spaces = spaces.len();

答案是會直接丟出error,因為編譯器已經知道這個變數是某個型別了,不能直接換成其他型別。

整數溢位

關於基礎型別(Primitive Type),尤其是整數!會有需要考慮到溢位的可能,但官方教學告訴了我們一些有趣的事:

const NUM: u8 = 255;
let mut x = 1;
x += NUM;
println!("x is {}", x);

直接下

cargo run

Compiler會在編譯期間告訴我們overflow了

thread 'main' panicked at 'attempt to add with overflow', src\main.rs:4:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

但是如果是在release模式下編譯的話:

cargo run --release
Compiling basic v0.1.0 (D:\projects\rust_learning\basic)
    Finished release [optimized] target(s) in 0.35s
     Running `target\release\basic.exe`
x is 0

Rust會把它變成二的補數!

詳情請看這裡

轉型(Type casting)

這裡指的是基本型的轉型,一樣拿整數加減為舉例:

let x: u8 = 100;
let mut y: i32 = 1024;
y += x;
println!("y is {}", x);

Compiler會直接告訴你,型別不一樣,不能直接相加

Compiling basic v0.1.0 (D:\projects\rust_learning\basic)
error[E0308]: mismatched types
 --> src\main.rs:4:10
  |
4 |     y += x;
  |          ^ expected `i32`, found `u8`

error[E0277]: cannot add-assign `u8` to `i32`
 --> src\main.rs:4:7
  |
4 |     y += x;
  |       ^^ no implementation for `i32 += u8`
  |
  = help: the trait `AddAssign<u8>` is not implemented for `i32`
  = help: the following other types implement trait `AddAssign<Rhs>`:
            <f32 as AddAssign<&f32>>
            <f32 as AddAssign>
            <f64 as AddAssign<&f64>>
            <f64 as AddAssign>
            <i128 as AddAssign<&i128>>
            <i128 as AddAssign>
            <i16 as AddAssign<&i16>>
            <i16 as AddAssign>
          and 20 others

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.

這個就不像C++那樣,Compiler會幫你隱式轉換(implicit conversion),需要自己轉型,基本型別轉型的話是像這樣:

let x: u8 = 100;
let mut y: i32 = 1024;
y += x as i32; // 這裡轉型
println!("y is {}", y);

Reference


上一篇
[Rust] 安裝教學與Hello, World!
下一篇
[Rust] 靜態陣列與Tuple
系列文
嘗試30天學「不」會Rust18
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言