rust學習三、基本型別

正在战斗中發表於2024-10-29

本文內容摘自<<The rust programming language>>,作者:美國的steve klabnik ,Carol nichols。

中國工信出版社2020年出版,但在國外據說是2018年出版的。

關於本人的入門大部分來自此書。

不過此書由於出版的時間較早(假定是2018),那麼那個時候的rustc的版本是1.30左右,所以在1.81的環境上還是具有不少的出入。

需要在完成本書的基本學習之後,再研究1.81上的內容.

本文的目的在於作為一個筆記,讀者可以作為參考,也可以翻閱任意部落格或者網站上的。

一、概述

在作者的這個章節中,簡單介紹了基本概念:

  • 變數與可變性
  • 資料型別
  • 資料型別-標量型別
  • 資料型別-複合型別

rust的資料型別遠不止這些!

1.1、名稱風格_蛇形

rust推薦用蛇形風格,這和java,c++之類的不同。

我個人認為蛇形還是比較人性化的,一方面提升了輸入速度,其次可能還更好閱讀。

不過這個風格並非是強制的,但是rustc會多管閒事,在編譯的時候給出不少警告。

二、變數與可變性

這個變數的最重要概念之一,強調幾點:

1.變數具有可變和不可變屬性,和其它語言一樣。但是rust預設是不可變

2.編輯器可以保證不能修改不可變變數,這是重點

其它語言也有這種情況,不過沒有那麼突出。其它語言中預設是可變的,而rust是預設可變的

例如在JAVA中

int a=10;   
final int b=20;  //不可變需要顯示定義
a=99;
b=29; //這個會編譯錯誤

而rust是翻過來的:

let score=100;   //預設不可變
score=91;   //這個會編譯報錯
let mut age=90;  //要可變,需要顯示申明
age=99;

三、資料型別

原文只強調了一點:rust是靜態型別語言,所以在編譯的時候就需要知道所有變數的具體型別.

這就是靜態型別語言的特點,好處是避免潛在的錯誤,嚴謹的語言一般都支援這個。

不嚴謹的,也搞了一些手段避免過於散漫導致的問題,例如js。用const,let來避免可能的問題。

python也是動態型別的。

c,C++,java也是靜態型別語言.

四、資料型別-標量型別

所謂標量,即該型別主要是為了表示某種”量"。

在本文中,範圍很狹窄,就是數量。

所以有以下幾個標量型別:整數、浮點數(小數)、布林、字元

注意,最後一個是字元,不是字串.

有符號整數- i8/16/32/64/size ,分別表示8位,16位,32位,64位和平臺架構型別

無符號整數-u8/16/32/64/size ,分別表示8位,16位,32位,64位和平臺架構型別

浮點-f32,f64-rust預設推到字面量位f64,這是因為現代cpu更快,且f64提供更高的精度

字元(char)-但是它佔據四個位元組,是unicode,意味著可以展示各種語言的字元和一些表情包

注意,所謂平臺架構型別usize,isize,它們和作業系統cpu架構有關。如果是64位的,則是64,否則就是32.暫時沒有128之類的。

示例:

fn main(){
    //1.0 整數
    let my_age: u8=90;   // 0~255
    //let f_age:u8=300;    //溢位報錯
    let my_food_amount: u16=50000;   // 0~65535
    let ys=my_food_amount%9;

    let my_cells: u32= 1000000000;     //0~4294967295  ,即0到42億
    let star_qty: u64 = 9000000000000;          //0~18,446,744,073,709,551,615   即0~1844兆
    let max:u128 =9292;
    println!("my_age={},my_food_amount={},my_cells={},star_qty={},",
    my_age,my_food_amount,my_cells,star_qty);
    //    my_age=99; // 預設不可變,這樣會爆編譯錯誤

    //2.0 浮點數,浮點數運算是否存在精度丟失問題?
    let score:f32=90.4;            //-3.4 X 10³⁸-3.4 X 10³⁸
    let money:f64=3.1415926532758; //-1.8 X 10³⁰⁸   -   1.8 X 10³⁰⁸

    //3.0 布林  ,佔據一個位元組
    let is_ok=true;
    let is_successful=false;

    //4.0 字元型別,非字串型別
    let dog_tag:char='a';
    //列印常見的120幾個ascii字母
    let mut str:String=String::from("");
    let mut code:u8=0;
    for i in 1..255 {
        let ch=code as char;
        str=str+&ch.to_string();
        if (code%30==0){
            println!("{}",str);
            str=String::from("");
        }
        code += 1;
    }
    if (str!=""){
        println!("{}",str);
    }
    
    //演示重複定義一個變數,這在java這樣的語言中是不允許的
    
    let cat="小白";
    println!("{}",cat ); //
    let cat=90;
    println!("{}",cat);
    
    //字面表達標量型別
    let a1=10_i32;
    let a2=10.2_f32;
    let a3=10.554_f64;
    let a4=254u8;
    let a5=99.88_f32;
    println!("{},{},{},a4={},{}",a1,a2,a3,a4,a5);
}

示例中除了展示定義、訪問型別,還增加了字面量表達型別的方法 .

在前例中,都是一些常見的,但我們也很感興趣如何表示不同進位制的數字(原文例子):

    //字面量表達不同的整數
    let d1=10;
    let d2=0o10;     //8進位制  0o開頭
    let d3=0x10;     //16進位制 0x開頭
    let d4=0b01001;  //二進位制 0b開頭
    println!("d1={},d2={},d3={},d4={}",d1,d2,d3,d4);

列印結果如下:

五、資料型別-複合型別

複合型別,故名思意:該型別的值通常由多個標量型別組成。

本文提到了以下幾個:

元組(tuple),用的名稱同python一樣. 不可變長,但元素個數型別可以不一樣.。有點型別java的Object[]

陣列,不可變長,要求成員型別必須一致,類似java的 int[],char[]之類的

用於複合型別的時候,rust的語法還頗有python的樣子,比較隨意(也有人認為方便)

示例:

fn main(){
    //1.0 元組 tuple- 元素型別可以不同,個數不能變化
    //定義方式常見有兩種:指定每個元素的型別,或者不指定
    //總之這個tuple不知有啥用,訪問非常不方便,定義也非常靈活? 效能還是什麼?
    let i:u8=9;
    let my_nums=(0,1,2,3,4,5,6,7,8,99);
    let my_nums32:(u32,u32,u32,u32)=(1000,109393,29992,1992);
    //訪問元素的方式-使用點號加序號
    println!("my_nums is:{}",my_nums.9);
    
    //匹配獲取,但用於巨長的,並不適合
    let tuple = (1, "hello", 3.14);  
    let (a, b, c) = tuple;  
    println!("a: {}, b: {}, c: {}", a, b, c);


    //2.0 陣列 array    - 元素型別必須一致,個數不能變化
    //陣列的定義方式足夠靈活,訪問的方式也更靈活,更接近大部分程式語言,即可以透過索引下標訪問,索引從0開始
    let score_arr=[10,20,30,40];
    let food_arr=["大米","糙米","地瓜","包菜","白菜"];
    for i in 0..food_arr.len() {
        println!("第{}個食物:{}",i+1,food_arr[i]);
    }
    
    //3.0 
    print_food(&food_arr);
}

fn print_food(foods:&[&str]){
    for i in 0..foods.len() {
      println!("第{}個食物:{}",i+1,foods[i]);
    }
}

注意,上例中print_food的引數如果定義為 foods:[&str]那麼會導致編譯錯誤:doesn't have a size known at compile-time

相關文章