首页
关于
友链
其它
统计
壁纸
更多
留言
Search
1
cgroup--(4)cgroup v1和cgroup v2的详细介绍
6,701 阅读
2
修改Linux Kernel defconfig的标准方法
6,558 阅读
3
Android系统之VINTF(1)manifests&compatibility matrices
6,145 阅读
4
使用git生成patch和应用patch
3,697 阅读
5
c语言的__attribute__
3,203 阅读
默认分类
文章收集
学习总结
算法
环境配置
知识点
入门系列
vim
shell
Git
Make
Android
Linux
Linux命令
内存管理
Linux驱动
Language
C++
C
Rust
工具
软件工具
Bug
COMPANY
登录
Search
标签搜索
Rust
shell
Linux
c
uboot
Vim
vintf
Linux驱动
Android
device_tree
git
DEBUG
arm64
链表
数据结构
IDR
内核
ELF
gcc
ARM
adtxl
累计撰写
381
篇文章
累计收到
16
条评论
首页
栏目
默认分类
文章收集
学习总结
算法
环境配置
知识点
入门系列
vim
shell
Git
Make
Android
Linux
Linux命令
内存管理
Linux驱动
Language
C++
C
Rust
工具
软件工具
Bug
COMPANY
页面
关于
友链
其它
统计
壁纸
留言
搜索到
381
篇与
的结果
2024-12-10
Rust程序设计学习笔记(5)--枚举和模式匹配
仅是一些笔记,完整的rust学习文档详见https://rustwiki.org/zh-CN/book/title-page.html1. 定义枚举1.1 枚举值将 IP 地址的数据和 IpAddrKind 成员存储在一个 struct 中 #![allow(unused)] fn main() { enum IpAddrKind { V4, V6, } struct IpAddr { kind: IpAddrKind, address: String, } let home = IpAddr { kind: IpAddrKind::V4, address: String::from("127.0.0.1"), }; let loopback = IpAddr { kind: IpAddrKind::V6, address: String::from("::1"), }; } 以将任意类型的数据放入枚举成员中:例如字符串、数字类型或者结构体。甚至可以包含另一个枚举!如struct Ipv4Addr { // --snip-- } struct Ipv6Addr { // --snip-- } enum IpAddr { V4(Ipv4Addr), V6(Ipv6Addr), }枚举和结构体还有另一个相似点:就像可以使用 impl 来为结构体定义方法那样,也可以在枚举上定义方法。1.2 Option 枚举和其相对于空值的优势Option 是标准库定义的另一个枚举。Option 类型应用广泛是因为它编码了一个非常普遍的场景,即一个值要么有值要么没值。从类型系统的角度来表达这个概念就意味着编译器需要检查是否处理了所有应该处理的情况,这样就可以避免在其他编程语言中非常常见的 bug。编程语言的设计经常要考虑包含哪些功能,但考虑排除哪些功能也很重要。Rust 并没有很多其他语言中有的空值功能。空值(Null )是一个值,它代表没有值。在有空值的语言中,变量总是这两种状态之一:空值和非空值。空值的问题在于当你尝试像一个非空值那样使用一个空值,会出现某种形式的错误。因为空和非空的属性无处不在,非常容易出现这类错误。然而,空值尝试表达的概念仍然是有意义的:空值是一个因为某种原因目前无效或缺失的值。问题不在于概念而在于具体的实现。为此,Rust 并没有空值,不过它确实拥有一个可以编码存在或不存在概念的枚举。这个枚举是 Option<T>,而且它定义于标准库中,如下:enum Option<T> { Some(T), None, }Option<T> 枚举是如此有用以至于它甚至被包含在了 prelude 之中,你不需要将其显式引入作用域。另外,它的成员也是如此,可以不需要 Option:: 前缀来直接使用 Some 和 None。即便如此 Option<T> 也仍是常规的枚举,Some(T) 和 None 仍是 Option<T> 的成员。<T> 语法是一个我们还未讲到的 Rust 功能。它是一个泛型类型参数。目前,所有你需要知道的就是 <T> 意味着 Option 枚举的 Some 成员可以包含任意类型的数据。这里是一些包含数字类型和字符串类型 Option 值的例子:let some_number = Some(5); let some_string = Some("a string"); let absent_number: Option<i32> = None;如果使用 None 而不是 Some,需要告诉 Rust Option<T> 是什么类型的,因为编译器只通过 None 值无法推断出 Some 成员保存的值的类型。当有一个 Some 值时,我们就知道存在一个值,而这个值保存在 Some 中。当有个 None 值时,在某种意义上,它跟空值具有相同的意义:并没有一个有效的值。2. match控制流运算符Rust 有一个叫做 match 的极为强大的控制流运算符,它允许我们将一个值与一系列的模式相比较,并根据相匹配的模式执行相应代码。模式可由字面量、变量、通配符和许多其他内容构成;enum Coin { Penny, Nickel, Dime, Quarter, } fn value_in_cents(coin: Coin) -> u8 { match coin { Coin::Penny => { println!("Lucky penny!"); 1 } Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter => 25, } } fn main() {} 如上所示,match关键字后面是个表达式,这里是coin的值。接下来是match的分支。一个分支由模式和一些代码组成,中间使用=>做分开,每个分支间使用逗号分开。如果代码比较复杂,可以用{}括起来,并且后面不需要跟逗号。2.1 绑定值的模式匹配分支的另一个有用的功能是可以绑定匹配的模式的部分值。这也就是如何从枚举成员中提取值的。想象一下我们的一个朋友尝试收集所有 50 个州的 25 美分硬币。在根据硬币类型分类零钱的同时,也可以报告出每个 25 美分硬币所对应的州名称,这样如果我们的朋友没有的话,他可以将其加入收藏。在这些代码的匹配表达式中,我们在匹配 Coin::Quarter 成员的分支的模式中增加了一个叫做 state 的变量。当匹配到 Coin::Quarter 时,变量 state 将会绑定 25 美分硬币所对应州的值。接着在那个分支的代码中使用 state,如下:#[derive(Debug)] enum UsState { Alabama, Alaska, // --snip-- } enum Coin { Penny, Nickel, Dime, Quarter(UsState), } fn value_in_cents(coin: Coin) -> u8 { match coin { Coin::Penny => 1, Coin::Nickel => 5, Coin::Dime => 10, Coin::Quarter(state) => { println!("State quarter from {:?}!", state); 25 } } } fn main() { value_in_cents(Coin::Quarter(UsState::Alaska)); } 如果调用 value_in_cents(Coin::Quarter(UsState::Alaska)),coin 将是 Coin::Quarter(UsState::Alaska)。当将值与每个分支相比较时,没有分支会匹配,直到遇到 Coin::Quarter(state)。这时,state 绑定的将会是值 UsState::Alaska。接着就可以在 println! 表达式中使用这个绑定了,像这样就可以获取 Coin 枚举的 Quarter 成员中内部的州的值。2.2 匹配Option<T>我们想要编写一个函数,它获取一个 Option<i32> ,如果其中含有一个值,将其加一。如果其中没有值,函数应该返回 None 值,而不尝试执行任何操作。fn main() { fn plus_one(x: Option<i32>) -> Option<i32> { match x { None => None, Some(i) => Some(i + 1), } } let five = Some(5); let six = plus_one(five); let none = plus_one(None); } Rust 中的匹配是穷举式的(exhaustive):必须穷举到最后的可能性来使代码有效。3. if let 简单控制流if let 语法让我们以一种不那么冗长的方式结合 if 和 let,来处理只匹配一个模式的值而忽略其他模式的情况。let some_u8_value = Some(0u8); match some_u8_value { Some(3) => println!("three"), _ => (), }我们想要对 Some(3) 匹配进行操作但是不想处理任何其他 Some<u8> 值或 None 值。为了满足 match 表达式(穷尽性)的要求,必须在处理完这唯一的成员后加上 _ => (),这样也要增加很多样板代码。不过我们可以使用 if let 这种更短的方式编写。 #![allow(unused)] fn main() { let some_u8_value = Some(0u8); if let Some(3) = some_u8_value { println!("three"); } } if let 获取通过等号分隔的一个模式和一个表达式。它的工作方式与 match 相同,这里的表达式对应 match 而模式则对应第一个分支。可以在 if let 中包含一个 else。else 块中的代码与 match 表达式中的 _ 分支块中的代码相同,这样的 match 表达式就等同于 if let 和 else。
2024年12月10日
8 阅读
0 评论
0 点赞
2024-12-10
Rust程序设计学习笔记(4)--使用结构体组织关联数据
仅是一些笔记,完整的rust学习文档详见https://rustwiki.org/zh-CN/book/title-page.html1. 定义并实例化结构体定义结构体,需要使用 struct 关键字并为整个结构体提供一个名字。结构体的名字需要描述它所组合的数据的意义。接着,在大括号中,定义每一部分数据的名字和类型,我们称为 字段(field)。struct User { active: bool, username: String, email: String, sign_in_count: u64, } 要在定义结构体后使用它,我们可以通过为每个字段指定具体值的方式来创建该结构体的实例。创建一个实例需要以结构体的名字开头,接着在大括号中使用 key: value 键-值对的形式提供字段,其中 key 是字段的名字,value 是需要存储在字段中的数据值。实例中字段的顺序不需要和它们在结构体中声明的顺序一致。换句话说,结构体的定义就像一个类型的通用模板,而实例则会在这个模板中放入特定数据来创建这个类型的值。struct User { active: bool, username: String, email: String, sign_in_count: u64, } fn main() { let mut user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; user1.email = String::from("anotheremail@example.com"); } 使用结构体更新语法从其他实例创建实例使用旧实例的大部分值但改变其部分值来创建一个新的结构体实例通常很有用。这可以通过结构体更新语法(struct update syntax)实现。struct User { active: bool, username: String, email: String, sign_in_count: u64, } fn main() { // --snip-- let user1 = User { email: String::from("someone@example.com"), username: String::from("someusername123"), active: true, sign_in_count: 1, }; let user2 = User { email: String::from("another@example.com"), ..user1 }; } 代码创建了一个新实例 user2,该实例具有不同的 email 值,但 username、 active 和 sign_in_count 字段的值与 user1 相同。..user1 必须放在最后,以指定其余的字段应从 user1 的相应字段中获取其值,但我们可以选择以任何顺序为任意字段指定值,而不用考虑结构体定义中字段的顺序。使用没有命名字段的元组结构体来创建不同的类型也可以定义与元组类似的结构体,称为元组结构体(tuple struct)。元组结构体有着结构体名称提供的含义,但没有具体的字段名,只有字段的类型。当你想给整个元组取一个名字,并使元组成为与其他元组不同的类型时,元组结构体是很有用的,这时像常规结构体那样为每个字段命名就显得多余和形式化了。struct Color(i32, i32, i32); struct Point(i32, i32, i32); fn main() { let black = Color(0, 0, 0); let origin = Point(0, 0, 0); } 通过派生trait增加实用功能增加属性来派生 Debug trait,并使用调试格式打印 Rectangle 实例#[derive(Debug)] struct Rectangle { width: u32, height: u32, } fn main() { let rect1 = Rectangle { width: 30, height: 50, }; println!("rect1 is {:?}", rect1); } 2. 方法语法方法 与函数类似:它们使用 fn 关键字和名称声明,可以拥有参数和返回值,同时包含在某处调用该方法时会执行的代码。不过方法与函数是不同的,因为它们在结构体的上下文中被定义(或者是枚举或 trait 对象的上下文),并且它们第一个参数总是 self,它代表调用该方法的结构体实例。2.1 定义方法#[derive(Debug)] struct Rectangle { width: u32, height: u32, } impl Rectangle { fn area(&self) -> u32 { self.width * self.height } } fn main() { let rect1 = Rectangle { width: 30, height: 50, }; println!( "The area of the rectangle is {} square pixels.", rect1.area() ); } 为了使函数定义于 Rectangle 的上下文中,我们开始了一个 impl 块(impl 是 implementation 的缩写),这个 impl 块中的所有内容都将与 Rectangle 类型相关联。接着将 area 函数移动到 impl 大括号中,并将签名中的第一个(在这里也是唯一一个)参数和函数体中其他地方的对应参数改成 self。&self实际上是 self: &Self 的缩写。在一个 impl 块中,Self 类型是 impl 块的类型的别名。方法的第一个参数必须有一个名为 self 的Self 类型的参数,所以 Rust 让你在第一个参数位置上只用 self 这个名字来缩写。2.2 关联函数所有在 impl 块中定义的函数被称为关联函数(associated function),因为它们与 impl 后面命名的类型相关。我们可以定义不以 self 为第一参数的关联函数(因此不是方法),因为它们并不作用于一个结构体的实例。我们已经使用了一个这样的函数,String::from 函数,它是在 String 类型上定义的。关联函数经常被用作返回一个结构体新实例的构造函数。例如我们可以提供一个关联函数,它接受一个维度参数并且同时作为宽和高,这样可以更轻松的创建一个正方形 Rectangle 而不必指定两次同样的值:#[derive(Debug)] struct Rectangle { width: u32, height: u32, } impl Rectangle { fn square(size: u32) -> Rectangle { Rectangle { width: size, height: size, } } } fn main() { let sq = Rectangle::square(3); } 使用结构体名和 :: 语法来调用这个关联函数:比如 let sq = Rectangle::square(3);。这个方法位于结构体的命名空间中::: 语法用于关联函数和模块创建的命名空间。
2024年12月10日
9 阅读
0 评论
0 点赞
2024-12-10
Rust程序设计学习笔记(3)--认识所有权
仅是一些笔记,完整的rust学习文档详见https://rustwiki.org/zh-CN/book/title-page.html
2024年12月10日
11 阅读
0 评论
0 点赞
2024-12-09
Rust程序设计学习笔记(2)--通用编程概念
仅是一些笔记,完整的rust学习文档详见https://rustwiki.org/zh-CN/book/title-page.html
2024年12月09日
6 阅读
0 评论
0 点赞
2024-11-22
Linux Kernel 之九 详解 virtio-net 源码框架、执行流程
转载自https://blog.csdn.net/ZCShouCSDN/article/details/132361829
2024年11月22日
93 阅读
0 评论
0 点赞
2024-11-09
Rust程序设计学习笔记(1)--环境安装与导览
暂无简介
2024年11月09日
28 阅读
0 评论
0 点赞
2024-11-04
ARMv9--机密计算架构(CCA)深入理解
转载自https://developer.aliyun.com/article/1205005
2024年11月04日
55 阅读
0 评论
0 点赞
2024-10-30
一些信息安全中术语的理解
整理自网络
2024年10月30日
32 阅读
0 评论
0 点赞
2024-10-30
ARM Trusted Firmware分析——镜像签名/加密/生成、解析/解密/验签
转载自https://www.cnblogs.com/arnoldlu/p/14332530.html跟着博主的文章把安全启动早期的工作过一下
2024年10月30日
53 阅读
0 评论
0 点赞
2024-10-29
长安欧尚Z6 idd 搭电启动
长时间不开车的小电瓶可能就亏电了,搭电方式如下:从发动机保险盒搭电,参考如下:
2024年10月29日
155 阅读
0 评论
0 点赞
1
2
3
...
39