当前位置: 首页 > news >正文

Rust 语言常见的一些概念(上)

目录

1、变量的可变性

常量

 隐藏

2、数据类型

2.1 标量类型

整型

浮点型

数值运算

布尔型

字符类型

复合类型

元组类型

数组类型


1、变量的可变性

变量默认是不可改变的(immutable)。这是 Rust 提供给你的众多优势之一,让你得以充分利用 Rust 提供的安全性和简单并发性来编写代码。不过,你仍然可以使用可变变量。

接下来我们测试一下,使用 cargo new variables命令在 projects 目录生成一个叫做 variables的新项目。

修改main.rs,内容如下所示:

fn main() {let v = 1;v = 2;println!("Hello, world! {v}");
}

在VSCode中打开,我们发现rust-analyzer插件有提示,无法修改不可变变量。

不过可变性也是非常有用的,可以用来更方便地编写代码。尽管变量默认是不可变的,你仍然可以在变量名前添加 mut 来使其可变,代码改成如下所示:

fn main() {let mut v = 1;println!("Hello, world! {v}");v = 2;println!("Hello, world! {v}");
}

常量

类似于不可变变量,常量 (constants) 是绑定到一个名称的不允许改变的值,不过常量与变量还是有一些区别。

首先,不允许对常量使用 mut。常量不光默认不可变,它总是不可变。声明常量使用 const 关键字而不是 let,并且必须声明值的类型。

把上面代码改成如下所示:

fn main() {const PI: f64 = 3.14159;println!("Hello, world! {PI}");
}

 隐藏

在同一作用域内,可以多次声明一个变量,可以用相同变量名称来隐藏一个变量,以及重复使用 let 关键字来多次隐藏,如下所示:

fn main() {let name = "zhangsan";let name = "lisi";println!("我的名字是:{name}");{let name = "wangwu";let name = "zhaoliu";println!("我的名字是:{name}");}
}

会打印对应的结果,但是重复定义的地方会有提示,说变量未引用,如果是有意为之的,建议加一个下划线的前缀。

隐藏与将变量标记为 mut 是有区别的。当不小心尝试对变量重新赋值时,如果没有使用 let 关键字,就会导致编译时错误。通过使用 let,我们可以用这个值进行一些计算,不过计算完之后变量仍然是不可变的。

mut 与隐藏的另一个区别是,当再次使用 let 时,实际上创建了一个新变量,我们可以改变值的类型,并且复用这个名字。例如,假设程序请求用户输入空格字符来说明希望在文本之间显示多少个空格,接下来我们想将输入存储成数字(多少个空格):

fn main() {let spaces = "zhangsan";let spaces = spaces.len();println!("长度是:{spaces}")
}

在编辑中可以看到同一个变量被赋值,对应的类型也改变了。

第一个 spaces 变量是字符串类型,第二个 spaces 变量是数字类型。隐藏使我们不必使用不同的名字,如果我们通过mut声明为可变变量,再看下会怎么样?

fn main() {let mut spaces = "zhangsan";spaces = spaces.len();println!("长度是:{spaces}");
}

这说明刚开始的时候,我们声明变量的类型已固定,我们不能改变变量的类型了。

2、数据类型

每一个值都属于某一个 数据类型data type),这告诉 Rust 它被指定为何种数据,以便明确数据处理方式。我们将看到两类数据类型子集:标量(scalar)和复合(compound)

使用 parse 将 String 转换为数字时,必须增加类型注解,像这样:

let guess:u32 = "100".parse().expect("");

如果没有对guess添加类型定义,会出现以下错误:

2.1 标量类型

标量scalar)类型代表一个单独的值。Rust 有四种基本的标量类型:整型、浮点型、布尔类型和字符类型。

整型

整数 是一个没有小数部分的数字。前面示例中使用过 u32 整数类型。该类型声明表明,它关联的值应该是一个占据 32 比特位的无符号整数(有符号整数类型以 i 开头而不是 u),以下表格展示了 Rust 内建的整数类型。

长度有符号无符号
8-biti8u8
16-biti16u16
32-biti32u32
64-biti64u64
128-biti128u128
archisizeusize

isize 和 usize 类型依赖运行程序的计算机架构:64 位架构上它们是 64 位的,32 位架构上它们是 32 位的。

注意:可以是多种数字类型的数字字面值允许使用类型后缀,例如 57u8 来指定类型,同时也允许使用 _ 做为分隔符以方便读数,例如1_000,它的值与你指定的 1000 相同。

数字字面值例子
Decimal (十进制)98_222
Hex (十六进制)0xff
Octal (八进制)0o77
Binary (二进制)0b1111_0000
Byte (单字节字符)(仅限于u8)b'A'

浮点型

Rust 也有两个原生的 浮点数floating-point numbers)类型,它们是带小数点的数字。Rust 的浮点数类型是 f32 和 f64,分别占 32 位和 64 位。默认类型是 f64,因为在现代 CPU 中,它与 f32 速度几乎一样,不过精度更高。所有的浮点型都是有符号的。

这是一个展示浮点数的实例:

浮点数采用 IEEE-754 标准表示。f32 是单精度浮点数,f64 是双精度浮点数。

数值运算

Rust 中的所有数字类型都支持基本数学运算:加法、减法、乘法、除法和取余。整数除法会向零舍入到最接近的整数。以下是一些示例:

fn main() {let plus = 2 + 3;let sub = 5 - 2;let mul = 2 * 3;let div = 3 /2;let rem = 3 % 2;println!("{plus} - {sub} - {mul} - {div} - {rem}") 
}

布尔型

Rust 中的布尔类型有两个可能的值:true 和 false。Rust 中的布尔类型使用 bool 表示。例如:

fn main() {let a = false;let b:bool = true;print!("{a} {b}")
}

字符类型

Rust 的 char 类型是语言中最原生的字母类型。下面是一些声明 char 值的例子:

fn main() {let a = 'A';let b:char = 'a';println!("{a} - {b}")
}

复合类型

复合类型可以将多个值组合成一个类型。Rust 有两个原生的复合类型:元组(tuple)和数组(array)。

元组类型

元组是一个将多个其他类型的值组合进一个复合类型的主要方式。元组长度固定:一旦声明,其长度不会增大或缩小。

我们使用包含在圆括号中的逗号分隔的值列表来创建一个元组。元组中的每一个位置都有一个类型,而且这些不同值的类型也不必是相同的。这个例子中使用了可选的类型注解:

let tup: (char, f32, bool) = ('A', 3.2, true); 

tup 变量绑定到整个元组上,因为元组是一个单独的复合元素。为了从元组中获取单个值,可以使用模式匹配(pattern matching)来解构(destructure)元组值,像这样:

fn main() {let tup: (char, f32, bool) = ('A', 3.2, true); let (x,y,z) = tup;println!("{x} {y} {z}") // A 3.2 true
}
数组类型

另一个包含多个值的方式是 数组array)。与元组不同,数组中的每个元素的类型必须相同。Rust 中的数组与一些其他语言中的数组不同,Rust 中的数组长度是固定的。

fn main() {let x = [1, 2, 3, 4, 5];
}

你还可以通过在方括号中指定初始值加分号再加元素个数的方式来创建一个每个元素都为相同值的数组:

fn main() {let a = [3; 5];
}

变量名为 a 的数组将包含 5 个元素,这些元素的值最初都将被设置为 3。这种写法与let a = [3,3,3,3,3]效果一样。

访问数组元素

fn main() {let x = [1, 2, 3, 4, 5];let y = x[0];let z = x[9];println!("{z}")
}

我们可以通过数组的索引去取值,跟js,ts语言取值一样。

当访问超过边界的索引时,会报一个运行时的错。

程序在索引操作中使用一个无效的值时导致 运行时 错误。程序带着错误信息退出,并且没有执行最后的 println! 语句。当尝试用索引访问一个元素时,Rust 会检查指定的索引是否小于数组的长度。如果索引超出了数组长度,Rust 会 panic,这是 Rust 术语,它用于程序因为错误而退出的情况。这种检查必须在运行时进行,特别是在这种情况下,因为编译器不可能知道用户在以后运行代码时将输入什么值。

相关文章:

  • 《Pytorch新手入门》第一节-认识Tensor
  • 如何选一款适合自己的网页浏览器?-2023
  • linux杀毒软件下载、安装(在线安装、离线安装)
  • CentOS Stream9 修改阿里源
  • C++基础算法④——排序算法(快速、归并附完整代码)
  • 【ARM Trace32(劳特巴赫) 使用介绍 2 -- Trace32 cmm 脚本基本语法及常用命令】
  • 理解springboot那些过滤器与调用链、包装或封装、设计模式相关等命名规范,就可以读懂80%的springboot源代码,和其他Java框架代码
  • 在react中使用redux react-redux的使用demo
  • 【c++|opencv】二、灰度变换和空间滤波---1.灰度变换、对数变换、伽马变换
  • 我的创作纪念日1024
  • 国家数据局正式揭牌,数据专业融合型人才迎来发展良机
  • 【咕咕送书 | 第5期】国家数据局正式揭牌,数据专业融合型人才迎来发展良机
  • 39基于matlab的全局路径规划算法中的快速扩展随机树RRT路径规划算法及其改进方法
  • InfoHound:一款针对域名安全的强大OSINT工具
  • Tiny Plane固定翼小飞机机身硬件整理开源
  • CentOS6 编译安装 redis-3.2.3
  • ERLANG 网工修炼笔记 ---- UDP
  • leetcode386. Lexicographical Numbers
  • mysql 5.6 原生Online DDL解析
  • Python_OOP
  • SpiderData 2019年2月25日 DApp数据排行榜
  • ubuntu 下nginx安装 并支持https协议
  • vue.js框架原理浅析
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 给自己的博客网站加上酷炫的初音未来音乐游戏?
  • 七牛云 DV OV EV SSL 证书上线,限时折扣低至 6.75 折!
  • 学习ES6 变量的解构赋值
  •  一套莫尔斯电报听写、翻译系统
  • AI又要和人类“对打”,Deepmind宣布《星战Ⅱ》即将开始 ...
  • hi-nginx-1.3.4编译安装
  • Python 之网络式编程
  • shell使用lftp连接ftp和sftp,并可以指定私钥
  • TPG领衔财团投资轻奢珠宝品牌APM Monaco
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • #pragam once 和 #ifndef 预编译头
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (1综述)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练
  • (LeetCode C++)盛最多水的容器
  • (分享)自己整理的一些简单awk实用语句
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题
  • .apk 成为历史!
  • .a文件和.so文件
  • .chm格式文件如何阅读
  • .libPaths()设置包加载目录
  • .Net Framework 4.x 程序到底运行在哪个 CLR 版本之上
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .net 使用$.ajax实现从前台调用后台方法(包含静态方法和非静态方法调用)
  • .NET 应用架构指导 V2 学习笔记(一) 软件架构的关键原则
  • []FET-430SIM508 研究日志 11.3.31
  • [BUUCTF]-PWN:wustctf2020_number_game解析(补码,整数漏洞)