- 2025-01-20
-
回复了主题帖:
EEWorld 2024年度人物:感恩相伴,共赴新程,携手努力!
谢谢论坛
- 2024-11-12
-
加入了学习《【2024 DigiKey创意大赛】+智慧焊接工作台》,观看 智慧焊接工作台
- 2024-06-30
-
回复了主题帖:
《Rust实战》书友互动第十一集:内核
吾妻思萌 发表于 2024-6-28 09:02
一个小问题:
作为业余感兴趣去学习Rust的有一丝丝编程基础的人,Rust是否是太过于coding硬核了,像是很 ...
接触这个语言主要是碰到有些网络通信协议用到了这个语言
- 2024-06-19
-
回复了主题帖:
《Rust实战》书友互动第十集:进程、线程和容器
rust线程之间的通信手段有哪些?
- 2024-06-16
-
发表了主题帖:
rust实战-数据1
## 1.数据
* 在println!中的{:016b}打印16位的二进制数据,位数不顾左侧补零;
* 在println!中的{:032b}打印32位的二进制数据,位数不顾左侧补零;
* `std::mem::transmute()` 把一个f32直接解释成(转换)一个u32,但是这种强行转换在rust被认为是一种混乱的行为,所以在使用此转换时需要使用unsafe包装,此代码块中编译器不提供内存安全性的保证:
```rust
let a: f32 = 42.42;
let frankentype: u32 = unsafe {
std::mem::transmute(a) // 此花括号里面没有分号,所以此表达式的结果将被传到其外部作用域中;
};
```
- 2024-05-26
-
发表了主题帖:
rust实战-生命周期、所有权、引用 4
## 4、生命周期、所有权、引用
rust 中的移动指的是所有权的移动,而不是数据的移动;
### 4.1 基本类型的特殊行为
* rust 中基本类型是有特殊行为的:这些类型实现了copy trait,基本类型具有复制语义,其他类型都具有移动语义;
* 如果一个函数获取了参数的所有权,那么此函数的外部作用域中,该参数所对应的值就无法再被访问了;
### 4.2 所有权
* 在不需要完整所有权的地方,使用引用;
* 重构代码,减少长存活期的值;
* 在需要完整所有权的地方,复制长存活期的值;
* 把数据包装到能帮助解决移动问题的类型中;
* 降低所需的访问级别,不去请求所有权,就需要在函数定义中使用引用(使用引用来避免所有权的问题),对于只读的访问使用&T,对于读写的访问使用&mut T;
* 在函数希望调整其参数的生命周期时,需要参数的所有权;
* 使用所有权,to变量的所有权移动到send()中,当send()返回时同就被删除:
```rust
fn send(to: CubeSat, msg: Message){
to.mailbox.message.push(msg);
}
```
* 使用一个可变的引用,在CubeSat类型上添加&mut 前缀,这允许在外部作用域中一直持有to变量所指向的数据的所有权;
```rust
fn send(to: &mut CubeSat, msg: Message){
to.mailbox.message.push(msg);
}
```
* 每个对象有唯一的所有者,这需要对软件进行大量的提前规划和重构;
* 重构工作量通常比较大,有时可以通过复制值来替代重构,虽然这将会带来一些额外的开销,但这种方法还是比较有用的。在rust的基本数据类型已经集成了copy方法,而且这种复制方法在CPU是开销比较低的,所以直接使用复制就可以避免去考虑对象的所有权的移动;
* 由实现了copy的类型所组成的类型来派生copy,`#[derive(Copy,Clone,Debug)]`会告诉编译器自动为每个trait添加一个copy实现;
* rust允许程序员选择性使用垃圾收集器---使用wrapper(包装器);
* RT表示一个类型为T的引用计数值,其提供了T的共享式所有权,共享式所有权能够防止T从内存中被删除,直到所有的所有者都被删除为止;引用计数用来跟踪有效引用的,每当创建出一个引用的时候,其内部的计数器就会加一,同样每当引用被删除的时候,该计数器就会减一,如果此计数器的值变成零了,那么T也就被删除了;
- 2024-05-23
-
回复了主题帖:
《Rust实战》书友互动第六集:内存,有啥你不熟悉的吗?
哪位大佬总结一下Rust管理内存有哪些方式?
- 2024-05-12
-
发表了主题帖:
rust实战-复合数据类型3
本帖最后由 IC爬虫 于 2024-5-12 17:47 编辑
## 3、复合数据类型
### 3.1 特殊返回值
* 有些返回值是由符号而不是文字组成的;
* ()类型的返回值叫做单元类型,可以用来表示一个函数没有返回值,没有返回类型的函数会返回();
* 以分号结尾的表达式也返回(),如果不想函数返回一个单元类型,就要注意函数的最后一个表达式不应该以分号结尾;
* !类型叫做Never类型,用于表示一个函数永不返回,如果一个函数保证会奔溃时,那么将永不返回;
### 3.2 方法
* 方法就是与某个对象耦合在一起的函数;
* 方法不需要指定其中一个参数的函数;
* 方法在调用时使用点操作符,并且允许其主对象隐式的传入;
* 使用impl代码块定义方法,示例:
```rust
impl FiLE{ //impl 代码块
fn new(name: &str) -> File { //File::new()就是一个普通的函数,需要高速rust此函数将返回一个File
File {
name: String::from(name),
data: Vec::new(), //File::new()仅仅是封装了创建对象语法,这也是不同的语法
}
}
}
```
### 3.3 正确、错误返回值
* 一个全局变量静态可变(可变静态),它拥有静态生命周期,在程序的整个生命周期它都是有效的;
* 可变全局变量使用static mut来表示;
* 惯例全局变量名使用全大写;
* 使用const关键字表示永不变的值;
* 要访问并修改可变静态变量,必须使用unsafe块,也就是编程人员需要承担编译器的职责,对unsafe块中的代码进行负责;
* const和let的区别:let定义的变量默认值是不可变的,但是let后面的数据还是可能被修改的->rust允许某些类型有一个明显矛盾的内部可变性的属性;
* 使用Result提供了编译器辅助下的代码正确性,其是标准库中定义的一个枚举体,它与其他的类型有着相同的地位;
### 3.4 枚举
* 枚举体是一个类型,可以表示多个已知的选项;
* 将枚举与rust的模式匹配功能一起使用,可以帮助你的代码健壮和易读;
* 与结构体类似,枚举同样支持使用impl块来实现方法;
* 使用枚举比使用常量数组更加强大易理解;
* 枚举体中的每个元素使用逗号隔开,以后以元素也是使用逗号结尾;
### 3.5 使用trait定义共有的行为
* trait让编译器知道,有多个类型试图执行同一个任务;
* trait关键字用于定义一个trait,而impl关键字可以用来给一个具体的类型附加上某个trait;
- 2024-05-06
-
回复了主题帖:
《Rust实战》书友互动第四集:生命周期、所有权和借用
lugl4313820 发表于 2024-5-6 17:28
Rust的所有权系统是非常出色的。但是用得不好,就会让你遇到不少的麻烦。文中提到有哪4个解决所有权的策略 ...
1、在不需要完整所有权的地方使用引用;
2、重构代码,减少长存活期的值;
3、在需要完整所有权的地方复制长存活期的值;
4、把数据包装到能帮助解决移动问题的类型中;
- 2024-04-28
-
回复了主题帖:
rust实战-rust语法2
hellokitty_bean 发表于 2024-4-28 10:27
“通过切片可以获得对原数据快速、只读的访问,而不需要任何形式的复制”
对这一句深为迷惑 ...
对
- 2024-04-27
-
发表了主题帖:
rust实战-rust语法2
### 2.4 语法2
* 字符串的方法`lines()`表示按行迭代;
* 字符串的方法`contains()`表示支持文本查找是否有包含的字段;
* String字符串类型和C语言中的类似,可以进行字符串的拼接、将新字符串附加到现有字符串上、可以修建空白符、使用动态内存分配存储它所表示的文本;
* str是高性能但功能较少的字符串类型,一旦被创建就不能再被扩大或者缩小,可以被认为是只读的数据,类似创建了一个固定长度的数组;
* rust中最常用用于表示数据列表的数据类型为数组和动态数组,其中动态数组是可增长的,但是会带来运行开销;
* [T;n]表示的数组类型中,T是数组元素的数据类型,n是一个非负的整数表示为定义的数组的长度;
* 数组类型和切片类型是不同的,切片类型是没有编译期长度的;
* rust会对数组索引做边界的检查,请求的元素超出数组的边界将会使程序奔溃,而不会返回错误的数据;
* 切片(slice)是动态大小的类型组对象,动态大小指的是编译期长度位置,和数组类似也是不能扩展和收缩的,这里的动态指的是动态的类型,而不是说长度是可变的;
* 切片更容易实现trait,这是因为其本身不需要与特定的长度进行绑定;
* 通过切片可以获得对原数据快速、只读的访问,而不需要任何形式的复制
* 动态数组(vector)是一个元素类型为T的可增长列表;
* rust使用`cargo add`添加第三方代码,再执行`cargo build`将会开始下载刚添加的第三方代码;
* rustup提供了访问多个编译器工具链的能力,还有访问语言级文档的功能;
- 2024-04-21
-
发表了主题帖:
rust实战-rust语法1
本帖最后由 IC爬虫 于 2024-4-21 22:17 编辑
### 2.4 语法
* rust没有goto关键字,沟通提供了跳转到程序其他部分的能力,goto会使得程序的控制流程变得混乱,可以使用循环标签实现这种跳转模式;
* 在rust 的if语法中不能使用0或者空字符串代表false,而其他值代表true,唯一可以用作true的值就是true自己,同样的可以用作false的值也只有false自己;
* rust是一门基于表达式的语言,所有表达式都会有返回值,而且大部分东西都是表达式,在rust的惯用语法中,函数会省略return关键字;
* rust会通过条件表达式给变量赋值;
* break关键字也可以返回一个值;
* 比条件语句 if else更安全的选择是match,当你没有考虑到所有可能时match会报警告;为了匹配多个可能的值提供以下三种语法:
* 匹配范围`10 ..=20`->会匹配此范围内的所有制;
* 布尔或`|`->会匹配两端的任何一个值;
* 下划线`_`->会匹配所有值;
* match有点类似c语言中的switch,但是和switch不同的是match要保证一个类型的所有可能情况都会显式地得到处理;如果match的各个分支没有覆盖到所有可能的情况,编译器将报错;另外入如果match匹配到一个分支后,match就会立即返回;
* 在rust的函数定义中,必须显式的制定函数的参数类型和返回值类型;
* rust中引用语法有点像指针的用法,避免复制开销;
* rust的安全性检查是基于生命周期系统的,因为生命周期系统能够验证所有对数据的访问是否有效;通常编译器自己可以推断出大部分参数的生命周期,但是有时推理参数的生命周期时会遇到困难,通常就直接报个错提示,此时编译器就需要协助了,这时生命周期注解就非常有必要了;
* 在rust中为了让函数能处理多种输入类型的数据使用泛型函数,在类型注释的位置上使用大写字母表示一个泛型类型,常用变量T、U、V来作为泛型类型的占位符,但实际上可以使用任意的其他名字,E经常用来表示错误类型;---泛型让代码可以重用;使用任意类型时需要注意,有写类型是不支持特定的操作的,这时就需要给这个任意类型做个限定-trait bound,比如:`fn add(i: T, j: T) -> T`这里表示要求T必须实现std::ops::Add,在这个trait限定中,使用了单个类型变量T,这保证了参数i和j以及函数的结果都是同一个类型,并且它们的类型都是支持加法运算的;