Rust 变量和基本类型

变量

  • Rust 支持声明可变的变量和不可变的变量,需要手动设定变量的可变性;
  • 相较于其他语言的变量赋值,Rust 叫变量绑定

不可变变量

设置变量 a 为字符串 “hello world”,相较于 go 的 var,在 rust 中使用 let,为了突出变量绑定的概念
let a = "hello world"

上述默认情况下,变量是不可变的,如下,编译会出问题,cannot assign twice to immutable variable。(无法对不可变的变量进行重复赋值)

fn main() {
    let x = "abc";
    println!("The value of x is: {}", x);
    x = "def";                               // 修改不可变的变量
    println!("The value of x is: {}", x);
}

可变变量

可以通过 mut 关键字让变量变为可变 的,如下

fn main() {
    let mut x = "abc";                       // 加上 mut,x 为可变变量
    println!("The value of x is: {}", x);
    x = "def";
    println!("The value of x is: {}", x);
}

注:mut只是可以修改变量,而不能修改类型。

使用下划线开头忽略未使用的变量

如果你创建了一个变量却不在任何地方使用它,Rust 通常会给你一个警告。但是有时创建一个不会被使用的变量是有用的。这时你希望告诉 Rust 不要警告未使用的变量,为此可以用下划线作为变量名的开头

fn main() {
    let _x = 5;
    let y = 10;
}

使用 cargo run 运行下试试:

# cargo run
   Compiling hello_world v0.1.0 (/opt/rust/hello_world)
warning: unused variable: `y`
 --> src/main.rs:4:9
  |
4 |     let y = 10;
  |         ^ help: if this is intentional, prefix it with an underscore: `_y`
  |
  = note: `#[warn(unused_variables)]` on by default

warning: `hello_world` (bin "hello_world") generated 1 warning
    Finished dev [unoptimized + debuginfo] target(s) in 0.35s
     Running `target/debug/hello_world`

可以看到,两个变量都没有使用,但是编译器却独独给出了 y 未被使用的警告。

注意:和 go 不同,go 编译报错,rust 只是编译 warning,可以运行。

变量解构

let 表达式不仅仅用于变量的绑定,还能进行复杂变量的解构:

fn main() {
    let (a, mut b): (bool,bool) = (true, false);
    // a = true,不可变; b = false,可变
    println!("a = {:?}, b = {:?}", a, b);

    b = true;
    assert_eq!(a, b);
}

解构式赋值

我们可以在赋值语句的左式中使用元组、切片和结构体模式。

struct Struct {
    e: i32
}

fn main() {
    let (a, b, c, d, e);

    (a, b) = (1, 2);
    // _ 代表匹配一个值,但是我们不关心具体的值是什么,因此没有是一个变量名而是使用了 _
    [c, .., d, _] = [1, 2, 3, 4, 5];
    Struct { e, .. } = Struct { e: 5 };

    assert_eq!([1, 2, 1, 4, 5], [a, b, c, d, e]);
}

这种使用方式跟之前的 let 保持了一致性,但是 let 会重新绑定,而这里仅仅是对之前绑定的变量进行再赋值。

需要注意的是,使用 += 的赋值语句还不支持解构式赋值。

变量和常量之间的差异

常量(constant)。与不可变变量一样,常量也是绑定到一个常量名且不允许更改的值,但是常量和变量之间存在一些差异:

  • 常量不允许使用 mut常量不仅仅默认不可变,而且自始至终不可变,因为常量在编译完成后,已经确定它的值。
  • 常量使用 const 关键字而不是 let 关键字来声明,并且值的类型必须标注。

下面是一个常量声明的例子,其常量名为 MAX_POINTS,值设置为 100,000。(Rust 常量的命名约定是全部字母都使用大写,并使用下划线分隔单词,另外对数字字面量可插入下划线以提高可读性):

const MAX_POINTS: u32 = 100_000;

变量遮蔽(shadowing)

Rust 允许声明相同的变量名,在后面声明的变量会遮蔽掉前面声明的,如下所示:

fn main() {
    let x = 5;
    let x = x + 1;

    println!("The value of x is: {}", x);
}

这个程序首先将数值 5 绑定到 x,然后通过重复使用 let x = 来遮蔽之前的 x,并取原来的值加上 1,所以 x 的值变成了 6。当运行此程序,将输出以下内容:

$ cargo run
...
The value of x is: 6

这和 mut 变量的使用是不同的,第二个 let 生成了完全不同的新变量,两个变量只是恰好拥有同样的名称,涉及一次内存对象的再分配
,而 mut 声明的变量,可以修改同一个内存地址上的值,并不会发生内存对象的再分配。

基本类型

Rust 像 go 一样编译时需要知道所有变量的类型,也可以自己推断导出变量的类型。
通常需要给一个显式的类型标注,例:

let guess: i32 = 32;
let x = "42".parse::<i32>();

数值类型

类型转换必须是显式的
Rust 数值可以使用方法,如浮点数取整 13.14_f32.round()

整数类型

长度有符号类型无符号类型
8 位i8u8
16 位i16u16
32 位i32u32
64 位i64u64
128-位i128u128
视架构而定isizeusize

cpu 是 32 位则 32位,cpu 是 64 为则为 64 位

和其他语言一样

  • 二进制 0b1010
  • 八进制 0o7654
  • 十六进制 0xfe
  • 字节 b’A’

Rust 整形默认使用 i32

整形溢出

在 debug 模式编译时,Rust 会检查整形的溢出,溢出会触发 panic
在 release 模式构建时,Rust 不会检查整形的溢出,按照补码循环溢出的规则处理,即 255 + 1 = 0

浮点类型

两种基本类型,32 位大小的 f32 和 64 位大小的 f64;

默认使用 f64。浮点数根据 IEEE-754 标准实现。f32 类型是单精度浮点型,f64 为双精度。

NaN

对于数学上未定义的结果,如取负数平方根,会产生特殊结果,Rust 的浮点数类型使用 NaN (Not a number) 来处理。
所有跟 NaN 交互的操作,都会返回一个 NaN,而且 NaN 不能用来比较;会触发 panic
可以使用 is_nan() 方法来判断数值是否是 NaN

数字运算和位运算

支持所有数字类型的基本数学运算:加法(+)、减法(-)、乘法(*)、除法(/)和取模(%)运算。
位运算 与(&)、或(|)、异或(^)、位非(!)、左移(<<)、右移(>>)。

序列 Range

用于生成连续的数值,类似于 python 的 range(),1..5 为 1 到 4,1..=5 为 1 到 5
如 1 到 5,Python 中 range(1, 6);在 Rust 中

for i in 1..=5 {
	println!("{}",i);
}

只能应用与整数或字符类型,因为整数和字符类型是连续的。

有理数和复数

有理数和复数不在标准库,社区提供 Rust 数据库:num
使用方法:
在 Cargo.toml 中的 [dependencies] 下添加一行 num = “0.4.0”
代码中使用 num:

use num::complex::Complex;

 fn main() {
   let a = Complex { re: 2.1, im: -1.2 };
   let b = Complex::new(11.1, 22.2);
   let result = a + b;

   println!("{} + {}i", result.re, result.im)
 }

字符、布尔、单元类型

字符类型占用 4 个字节,Rust 中使用 ‘’ 来表示
布尔类型有两个可能的值:true 和 false,布尔值占用内存的大小为 1 个字节:
单元类型就是 (),唯一的值也是 ()

比如,你可以用 () 作为 map 的值,表示我们不关注具体的值,只关注 key。 这种用法和 Go 语言的 struct{} 类似,可以作为一个值用来占位,但是完全不占用任何内存。

语句、表达式

Rust 的函数体是由一系列语句组成,最后由一个表达式来返回值,例如:

fn add_with_extra(x: i32, y: i32) -> i32 {
    let x = x + 1; // 语句
    let y = y + 5; // 语句
    x + y // 表达式
}

前两行是语句,最后一行是表达式,相较于其他语言,Rust 需要区分语句和表达式

语句

完成了一个具体的操作,语句没有返回值,语句不能赋值给其他值。

表达式

表达式会进行求值,然后返回一个值;表达式不能包含分号。

在表达式后加上分号,它就会变成一条语句,不会返回一个值。如果不返回任何值,会隐式地返回一个 ()

函数

例子,和其他语言几乎一样。

fn add(i: i32, j: i32) -> i32 {
   i + j
 }

Rust 是强类型语言,因此需要为每一个函数参数都标识出它的具体类型。

函数就是表达式,有返回值,可以直接将返回值赋给调用者,函数的返回值就是最后一条表达式的返回值,也可以 return 提前返回。

特殊返回类型
无返回值()
例如单元类型 (),是一个零长度的元组。它没啥作用,但是可以用来表达一个函数没有返回值:

  • 函数没有返回值,那么返回一个 ()
  • 通过 ; 结尾的表达式返回一个 ()

发散函数
当用 ! 作函数返回类型的时候,表示该函数永不返回( diverge function ),特别的,这种语法往往用做会导致程序崩溃的函数。
使 panic

fn dead_end() -> ! {
  panic!("end!");
}

使无限循环


fn forever() -> ! {
  loop {
    //...
  };
}

参考:Rust
大多数为个人学习笔记,比较简化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值