首页
关于
Search
1
2023 年保研经验贴 [计算机-末九Rank50%-入北计清深-北计直博]
340 阅读
2
Linux Kernel-THP阅读分析[Hang up]
237 阅读
3
FreeBSD Kernel-编译环境搭建
217 阅读
4
Linux Kernel-编译调试环境搭建
166 阅读
5
CSAPP 1. 计算机系统漫游
146 阅读
内核
源码分析
阅读笔记
Rust
语法
习题
读书笔记
深入理解计算机系统
技术之外
开发
rcore-arm
登录
Search
yyi
累计撰写
46
篇文章
累计收到
0
条评论
首页
栏目
内核
源码分析
阅读笔记
Rust
语法
习题
读书笔记
深入理解计算机系统
技术之外
开发
rcore-arm
页面
关于
搜索到
21
篇与
的结果
2023-08-04
Rust入门笔记 1.概述、变量与基本类型
Rust入门笔记 —— 概述,变量与基本类型在我学习的过程中,一直坚持着实践掌握的更快的方法论。本笔记是我使用Rust By Example和practice.rs学习Rust过程的记录,可能更多偏向于后者,因为他是中文的... 。我打算使用的路线是通过这两个Wiki快速掌握Rust的语法,然后阅读一些优秀的项目来让自己的代码变的优雅。最后开发几个中型项目来巩固,可能会包括Redis(我一直想通过开发的方式让我深入了解Redis)和一个小内核(如果时间允许),或者一个小编译器(如果时间不允许)。我的最终目的是可以让Rust成为我在学习计算机系统结构中的主要开发语言。我使用 Vscode + Docker作为我的学习环境,我对C/C++有比较高的熟练度,Python和Go也是我的主力语言。对其他语言也有一定了解,能勉强使用(如Swift、Java和Js)。我不认为Rust适合作为第一门语言学习。希望这能让你了解到我的大概水平,以便更好的让这篇笔记帮助到你。0 环境配置我是Windows下的,直接用Docker了docker run -it --name rust-dev --privileged=true \ -p 2222:22 -v /f/Dev_rs:/rs/work rust bash注意-v是挂载的目录,要符合你的实际情况-p是把docker的22端口映射到本机的2222端口上,方便使用CLion的ssh,入门期间没有太大的项目,以Vscode为主。1 变量、变量绑定Rust是一类静态语言,变量需要在初始化后使用通常,我们使用 let var_name[: var_type] = [value]; 的格式对变量进行声明。let有类似auto的功效,如果有value,可以不声明type,rust会自动进行类型推断。对于这种声明,我们称为把value绑定到变量1.1 变量与常量rust 包括变量和常量,其中变量还会分为可变变量和不可变变量,最显著的区别如下:let a = 123; // 被自动推断为i32, 如果需要,显式声明为i64 a = 456; // Error : cannot assign twice to **immutable** variable `a` let a = 456; // Right : 重新绑定了 // ---------------- const a: i32 = 123; // const 需要声明类型 let a = 456; // missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable1.2 可变变量注意到第三行报错中的immutable了么,我们需要显式的为一个变量声明为可变,才能在不重新绑定的前提下对其进行修改、运算等操作let mut a = 1; a += 2; println!("a = {}", a); // a = 3这里出现了一个 'println!',我们暂时不探究宏是什么以及他是怎么工作的,我们只需要知道它可以格式化的输出内容,形式上类似于Python的格式化字符串,即使你不会,你也能猜到它都输出了些什么,在上面的例子中,编译器把第二个参数a填入到了格式串的{}中,所以输出了 "a = 3" 的结果。1.3 未使用、未生明、作用域对于未使用的变量,rust编译器会报错。我们可以在变量前加'_',相当于显式的声明他是一个可能不会被用到的变量。fn main() { let a = 10; } // warning: unused variable: `a`rust编译器禁止使用未初始化的变量,会在编译期报错。对于变量作用域,和其他语言差不多,不做赘述。rust不允许全局的普通变量,必须是const或者static量1.4 变量遮蔽(Shadowing)变量遮蔽我理解类似于重载,在C中也很常见,只不过我们一般不这么用。后声明的变量只会在其作用域中有效,出了自己的作用域后就归还到原来的变量。fn main() { let x: i32 = 5; { assert_eq!(x, 5); let x = 12; assert_eq!(x, 12); } assert_eq!(x, 5); let x = 42; println!("{}", x); // 输出 "42". } 1.5 变量解构fn main() { let (mut x, y) = (1, 2); x += 2; assert_eq!(x, 3); assert_eq!(y, 2); }对于Python,我们经常使用对等的独立变量去接一个Tuple的拆分(典型的是函数返回值),Rust也可以这样在Rust 1.59+中,解构式还可以进行赋值。更多在后面 tuple 提到fn main() { let (mut x, mut y); (x, y) = (3, 4); [x, y] = [1, 2]; // 填空,让代码工作 assert_eq!([x,y], [1, 2]); } 2 基本类型2.1 数值类型对于整形,包括(8、16、32、64、128) x (i/u) 的笛卡尔积种,字面意思很好理解这个让我们填as后面的,了解到通过as进行字面量的强转fn main() { let v: u16 = 38_u8 as u16; }可以看到默认的字面整形量推断出来的变量类型是i32// 修改 `assert_eq!` 让代码工作 fn main() { let x = 5; assert_eq!("i32".to_string(), type_of(&x)); } // 以下函数可以获取传入参数的类型,并返回类型的字符串形式,例如 "i8", "u8", "i32", "u32" fn type_of<T>(_: &T) -> String { format!("{}", std::any::type_name::<T>()) } // 填空,让代码工作 fn main() { assert_eq!(i8::MAX, 127); assert_eq!(u8::MAX, 255); }对于字面量,用 [0-9_] 表示十进制数,0x[0-9A-F]表示十六进制数、0o、0b表示八进制、二进制数。对于浮点数,f32、f64分别代表32和64位浮点数,字面量默认为64位浮点数对于布尔,bool只能为true或者false, 不能用0代表false、非0代表true对于字符,用char表示,char大小为4个字节,是Unicode标量这个例子让我们改assert的char大小,因为是四字节,直接改为4// 修改2处 `assert_eq!` 让代码工作 use std::mem::size_of_val; fn main() { let c1 = 'a'; assert_eq!(size_of_val(&c1),4); // original : 1 let c2 = '中'; assert_eq!(size_of_val(&c2),4); // original : 3 println!("Success!") } 2.2 tuple & list用 () 表示 tuple 元组,典型的例子如下:let tup: (i32, f64, u8) = (500, 6.4, 1); // tup.0 等于 500 // tup.1 等于 6.4 // tup.2 等于 1 let (x, y, z) = tup; // y 等于 6.4imp函数返回的是一个空tuple (虽然暂时我还不知道为什么是这样),但是为了让它们相等,我们给v一个空tuple即可// 让代码工作,但不要修改 `implicitly_ret_unit` ! fn main() { let _v: () = (); let v = (); // Orig : (2, 3) assert_eq!(v, implicitly_ret_unit()); println!("Success!") } fn implicitly_ret_unit() { println!("I will return a ()") } // 不要使用下面的函数,它只用于演示! fn explicitly_ret_unit() -> () { println!("I will return a ()") }这个例子说明空tuple的占用空间为0,而非cpp中空类的1// 让代码工作:修改 `assert!` 中的 `4` use std::mem::size_of_val; fn main() { let unit: () = (); assert!(size_of_val(&unit) == 0); println!("Success!") }当然,tuple 也可以复合let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16);tuple可以直接通过下表解构、可以直接被 println 打印println!("{:?}", tuple_of_tuples.0); // (1, 2, 2)和 python 一样,需要一个 ', '区别括起来的数和 tupleprintln!("{:?} {:?}", (1), (1, )); // 1 (1,)用 [] 表示数组,包括同类型数据let a = [1, 2, 3, 4, 5]; // a 是一个长度为 5 的整型数组 let b = ["January", "February", "March"]; // b 是一个长度为 3 的字符串数组 let c: [i32; 5] = [1, 2, 3, 4, 5]; // c 是一个长度为 5 的 i32 数组 let d = [3; 5]; // 等同于 let d = [3, 3, 3, 3, 3]; let first = a[0]; let second = a[1]; // 数组访问 let first = a.get(0); // 会返回一个 Option,提供给我们 match 用,后面再说2.3 Rangerange的表达方式很简单,就是 a..b表示a到b左闭右开, 比如 -3..2表示 [-3, 2),a..=b表示闭区间两个目标: 1. 修改 assert! 让它工作 2. 让 println! 输出: 97 - 122fn main() { let mut sum = 0; for i in -3..2 { sum += i } assert!(sum == -5); for c in 'a'..='z' { println!("{}",c as u8); // original : no as u8 } }// 填空 use std::ops::{Range, RangeInclusive}; fn main() { assert_eq!((1..5), Range{ start: 1, end: 5 }); assert_eq!((1..=5), RangeInclusive::new(1, 5)); }
2023年08月04日
85 阅读
0 评论
0 点赞
1
...
4
5