Rust语言教程(2) - 从熟悉的部分开始
Rust语言教程(2) - 从熟悉的部分开始
虽然有默认不变性还有所有权的问题让Rust一上来用起来有些不同,但是其实大部分语法特点还是我们所熟悉的。
我们没必要上来就跟自己死磕,可以先从我们熟悉的部分开始学习。
一般我们写代码,使用的主要是数据类型、控制结构和函数。我们就从这三部分开始。
数据类型
与Go一样,Rust的定义语句数据也是放在变量名后面的,不过还要加上一个冒号。
布尔类型
布尔类型是bool:
let b0 : bool = true;
因为Rust是有类型推断的功能,所以很多时候可以不用指定类型。
let b1 = true;let b2 = !b1;let b3 = 1 > 0;println!("{} {} {}",b1,b2,b3);
如果使用CLion等IDE的话,就可以直接看到IDE提供的灰色的类型推断的提示,非常方便:
字符类型 - 传统与现代的结合
Rust的字符类型支持的是Unicode类型,占用4个字节。同时,Rust也支持单字节ASCII值,这时用b开头,类型值就是8位无符号类型u8。
我们来看例子:
let c1 :char = 'C';let c2:u8 = b'C';let c3 = '中';println!("{} {} {}",c1,c2,c3);
同样,我们可以将字符组成字符串,我们来看例子:
let s1 = "Hello";let s2 = b"World";println!("{} {:?}",s1,s2);
输出结果为:
Hello [87, 111, 114, 108, 100]
s1的真实类型是str类型,而s2是u8的数组。
let s1 :&str = "Hello";let s2 :&[u8;5] = b"World";
整数类型: 后缀与下划线齐飞
按照长度,Rust的整数类型支持8位,16位,32位,64位,128位。根据有符号和无符号,分为有符号的i8,i16,i32,i64,i128和无符号的u8,u16,u32,u64,u128。
除此之外,也有根平台相关的类型,有符号为isize类型,无符号为usize类型。
我们看下例子:
let i1 : i8 = -8;let i2 : i16 = -16;let i3 : i32 = -32;let i4 : i64 = -64;let i5 : i128 = -128;let u1 : u8 = 8;let u2 : u16 = 16;let u3 : u32 = 32;let u4 : u64 = 64;let u5 : u128 = 128;let p1 : isize = -1;let p2 : usize = 1;
上面都是跟其它语言比较像,下面我们来看看Rust特色的后缀。这在C++中也有,比如10l, 200L之类的。
在Rust中,我们直接用类型名做为后缀,我们看个例子:
let i6 = -1i8;let i7 = -2i16;
这样放在一起可能不太容易区分,没关系,Rust允许我们在数字上任意的加下划线来提升可读性,我们来看几个例子:
let i08 = -3_i32;let i09 = -4__i64;let i10 = -5___i128;
下划线并非只是用于数字和类型区分,也可以加在数字中间,我们来看个例子:
let u6 = 1_000_000_u128;println!("{}",u6);
默认的整数类型是i32,如果Rust无法推断中整数的类型,那么就默认为i32.
整数的进制
在Rust中,避免了077这样对八进制的偏爱,改为用0o来表示8进制整数。16进制仍然是0xFF前缀,二进制用0b前缀。
我们看例子:
let u07 = 0xFF_u32;let u08 = 0o7777_u32;let u09 = 0b01_10_00_u8;println!("{} {} {}",u07,u08,u09);
输出结果为:
255 4095 24
整数的溢出
在C语言中,整数的溢出也是一个常出现的问题。
对此,Rust在debug模式下,在编译时会检查整数的溢出的问题:
let i_10 : i8 = 0x7f;let i_11 : i8 = i_10 * 10i8;println!("{}",i_11);
在编译时,Rust就会报错:
84 | let i_11 : i8 = i_10 * 10i8;| ^^^^^^^^^^^ attempt to compute `i8::MAX * 10_i8`, which would overflow
懂程序分析的同学可能会想,在编译时检查不出来怎么办?好办,我们在运行时进行检查。
我们来个例子:
let mut i_20 : i8 = 0x20;for i in 1..20{i_20 = 0x20_i8 * i_20;}println!("{}",i_20);
在运行时仍然发现了溢出:
thread 'main' panicked at 'attempt to multiply with overflow', src/main.rs:91:16
stack backtrace:0: rust_begin_unwindat /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/std/src/panicking.rs:4831: core::panicking::panic_fmtat /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/panicking.rs:852: core::panicking::panicat /rustc/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/library/core/src/panicking.rs:503: tools::testat ./src/main.rs:914: tools::mainat ./src/main.rs:345: core::ops::function::FnOnce::call_onceat /Users/lusinga/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/src/rust/library/core/src/ops/function.rs:227
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
类型转换
Rust语言是强类型的语言,不像C一样有默认的类型转换。如果进行跨类型计算需要进行类型转换。
类型转换使用“as 类型”的方法来写,我们来看个例子:
let i_100 : i32 = (16i8 + 1) as i32;
i8计算之后还是i8,不能直接赋给i32类型,需要通过as i32来转换类型。
如果计算的类型不同,编译不报错,在运行的时候也会被检查出来。
我们看个例子:
let i_101 = 16i8 + 32i32;
会报下面的错:
error[E0308]: mismatched types--> src/main.rs:99:24|
99 | let i_101 = 16i8 + 32i32;| ^^^^^ expected `i8`, found `i32`
后面还有一个有趣的报错,让trait露了一个爪印:
error[E0277]: cannot add `i32` to `i8`--> src/main.rs:99:22|
99 | let i_101 = 16i8 + 32i32;| ^ no implementation for `i8 + i32`|= help: the trait `Add<i32>` is not implemented for `i8`
浮点数
浮点数跟C语言差不多,分为32位浮点数和64位浮点数,就这两种,分别是f32和f64。默认为f64。
我们来看两个例子:
let f_01 = 2.1;let f_02 = 2e8;
f_01和f_02都是f64类型。
需要注意的是,对于除0的处理,会引入两个新的值:
- 对于非0除以0,得到的将是无穷大inf
- 而对于0除以0,将得到NaN,意思是并不是一个数
我们来看例子:
let f_03 = 0.0 / 0.0;let f_04 = 1.0 / 0.0;println!("{} {}",f_03,f_04);
输出结果为:
NaN inf
NaN对应的本尊是std::f64::NAN,而inf是std::f64::INFINITY,我们将其排列在一起:
let f_03 = 0.0 / 0.0;let f_04 = 1.0 / 0.0;let f_05 = std::f64::INFINITY;let f_06 = std::f64::NAN;println!("{} {} {} {}",f_03,f_04,f_05,f_06);
输出结果为:
NaN inf inf NaN
32位和64位的无穷大都是无穷大,它们是相等的:
let f_10 = std::f32::INFINITY;let f_11 = std::f64::INFINITY;println!("{}",f_11==f_10 as f64);
输出结果为:
true
但是要注意的是,两个NAN是不相等的:
let f_12 = std::f64::NAN;println!("{}",f_12==f_12);
结果为false.
流程控制
分支语句
Rust支持if-else表达式,用来处理分支。
if后面不必加括号,有点像Go,我们看个例子:
if n >= 100 {println!("Grade A");}else if n>= 60 {println!("Pass");}else{println!("Fail");}
可以写成更像表达式一点的方式:
let grade = if n == 100{"A"}else if n>=60{"Pass"}else{"Fail"};
如果用作表达式的话,if和else两个分支返回的结果需要转换成同一类型,毕竟Rust是这么强类型的语言。
循环语句
Rust的循环分为三种:死循环loop,while循环和for循环。
loop最直接干脆,不需要while(true)
或者for(;;)
这种写法,直接loop。如果需要退出循环就用break,继续下一轮循环就用continue。
我们来个简单例子:
let mut num = 0;let mut sum = 0;loop{if num > 10 {break;}else{sum += num;num += 1;}}println!("sum={}",sum);
我们再将其翻译成while循环:
num = 0;sum = 0;while num <= 10 {sum += num;num += 1;}println!("sum={}", sum);
与if一样,while后面也不强制要求括号。
最后是for循环,它主要用于迭代器的遍历:
sum = 0;for i in 0..11 {sum += i;}println!("sum={}", sum);
函数
最后说下函数,Rust的函数使用fn关键字来定义。返回值的类型用->分隔而不是":"。
另外,Rust中不一定非要用return语句来返回值,表达式的值即可,我们看个例子:
fn fib2(n: i32) -> i64 {if n <= 2 {1i64} else {fib2(n - 1) + fib2(n - 2)}
}
按传统写法也是可以的:
fn fib2(n: i32) -> i64 {if n <= 2 {return 1i64} else {return fib2(n - 1) + fib2(n - 2)}
}
或者将return提到if表达式外面:
fn fib2(n: i32) -> i64 {return if n <= 2 {1i64} else {fib2(n - 1) + fib2(n - 2)}
}
小结
在使用基本类型的情况下,Rust跟C语言和Go语言的基础部分其实还是很类似的,熟悉Javascript等语言的同学也不会觉得陌生。我们可以把原有的知识迁移过来,基本类型变量如果需要修改值的话就加个mut。
Rust语言教程(2) - 从熟悉的部分开始相关推荐
- Rust语言教程(3) - 数组与向量
Rust语言教程(3) - 数组与向量 上一节我们采摘了不少低矮的果实,将其它语言学到的知识迁移到Rust 中来.这一节我们仍然继续采摘. 在数据结构中,最经常使用的就是定长的数组和变长的向量. 数组 ...
- Rust语言教程(4) - 字符串
Rust语言教程(4) - 字符串 有了数组和向量的基础,我们再来看它的一个特例:字符串. 字符串有两种表现形式,一种是基本类型,表示字符串的切片,以&str表示:另一种是可变的string类 ...
- Rust语言教程(1) - 一门没有GC的语言
缘起 本来这一系列文章并不在计划中.昨天跟赵磊和七哥讨论没有GC管理内存的问题. 讨论到没有GC情况下管理内存的学习曲线,七哥认为学习曲线不陡而是使用曲线陡.诚然,如果只有malloc和free,确实 ...
- 【一天一门编程语言】Rust 语言程序设计极简教程
文章目录 Rust 语言程序设计极简教程 介绍 安装 Rust Hello, World 基础语法 变量及数据类型 控制结构 `if` 语句 `while` 语句 `for` 语句 函数 泛型 泛型的 ...
- Rust学习教程02 - Rust语言简介
本文节选自<<Rust语言圣经>>一书 欢迎大家加入Rust编程学院,一起学习交流: QQ群:1009730433 进入Rust编程世界 一.Rust发展历程 Rust 最早是 ...
- 《安富莱嵌入式周报》第283期:全开源逆向“爆破”硬件工具,Linux内核6.1将正式引入RUST语言,I3C培训教程,80款市场成熟的电感式位置传感器设计
往期周报汇总地址:嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - P ...
- 微软再推 Rust 语言免费中文教程,更香了!
公众号关注 「奇妙的 Linux 世界」 设为「星标」,每天带你玩转 Linux ! 在过去的几个月,Amazon.Facebook.微软以及谷歌等科技巨头正疯狂吸纳人才市场上的 Rust 语言程序员 ...
- 【Rust 日报】2022-01-09 又一个Rust中文教程《Rust语言圣经》
12个Rust的Tips 使用 Cow<str> 作为返回类型 使用 Crossbeam channels 取代标准库 使用 Scopeguard 实现类似 Golang 的延迟运算 使用 ...
- RUST语言的编程范式
总是有很多很多人来问我对Rust语言怎么看的问题,在各种地方被at,其实,我不是很想表达我的想法.因为在不同的角度,你会看到不同的东西.编程语言这个东西,老实说很难评价,在学术上来说,Lisp就是很好 ...
- rust语言为什么没人用_为什么Rust语言正在兴起
rust语言为什么没人用 您可能从未用Mozilla创建的开源,系统级编程语言Rust编写任何东西,但是您可能会在某个时候写. 在Stack Overflow的2019年开发人员调查中 ,开发人员将R ...
最新文章
- 常用HTTP状态码趣(曲)解
- 用diff命令制作补丁
- ubuntu系统下安装php环境
- Java ObjectInputStream enableResolveObject()方法与示例
- 修改gitignore 后不起作用
- ASCII中关于大小写字母间隔为32的思考
- 【Vue】v-if 、v-show、v-for指令,最基础的流程控制和循环处理
- error:无法定位软件包
- 命令修改本地计算机策略,命令行修改本地组策略_通过命令行从Windows进行本地组管理...
- CGAL学习之路(三):CGAL读写点云
- 安装nodejs时:The error code is 2503.
- 两块同步FIFO实现乒乓操作
- 藏苹果 HNSUT 1889
- 金色css颜色代码大全,CSS颜色代码大全
- java基础语言+面向对象_经典案例——65个
- 移动互联网时代代驾app开发未来走向功能定制化
- 【Unity】物体爆炸,碎片横飞
- Advanced IP Scanner –免费的轻量级Windows端口扫描器
- saiku 安装配置
- 珍爱网退费流程?珍爱网怎么退费