rust学习三、基本类型
本文内容摘自<<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