Rust运算符
【图书介绍】《Rust编程与项目实战》-CSDN博客
《Rust编程与项目实战》(朱文伟,李建英)【摘要 书评 试读】- 京东图书 (jd.com)
https://blog.csdn.net/brucexia/category_12779443.html
前面已经学习了变量和常量,本节开始对它们进行操作,这就要用到Rust的操作符(Operator)。操作符通常是由一个或多个特殊的符号组成的(也有非特殊符号的操作符,如as),比如+、−、*、/、%、&、*等。每个操作符都代表一种动作(或操作),这种动作作用于操作数之上。简单来说,就是对操作数执行某种操作,然后返回操作后得到的结果。比如,加法操作3 + 2,这里的+是操作符,加号两边的3和2是操作数,加法符号的作用是对操作数3加上操作数2,得到计算结果5并返回5。
有些语言,很多操作符都是关键字,比如add、equals等。Rust的操作符主要是由符号组成的,比如+、−等。这些符号不在字母表中,但是在所有键盘上都可以找到。这个特点使得Rust程序更简洁,也更国际化。运算符也称操作符。运算符是Rust语言的基础,所以非常重要。
4.1.1 赋值运算符
赋值运算符的功能是将一个值赋给一个变量。比如:
a = 5;
以上代码将整数5赋给变量a。= 运算符左边的部分叫作左值(lvalue,left value),右边的部分叫作右值(rvalue,right value)。左值必须是一个变量,而右值可以是一个常量、一个变量、一个运算的结果,或者是前面几项的任意组合。
有必要强调赋值运算符永远是将右边的值赋给左边,不会反过来。比如:
a = b;
以上代码将变量b的值赋给变量a,不论赋值前a存储的是什么值,这行代码执行后,a的值就和b的值一样了。但要注意,我们只是将b的值赋给a,以后如果b的值改变了,并不会影响a的值。下面来看实例。
【例4.1】 赋值运算符的使用
在命令行下用命令cargo new myrust新建一个Rust项目,项目名是myrust。
打开VS Code,再打开文件夹myrust,然后在VS Code中打开src下的main.rs,输入如下 代码:
fn main() {let mut a:i32;let mut b:i32; //此时a、b的值未知a = 10; // a:10,b未知b = 4; // a:10,b:4a = b; // a:4,b:4b = 7; // a:4,b:7println!("{},{}",a,b);}
以上代码的结果是,a的值为4,b的值为7。最后一行中b的值被改变并不会影响a,虽然在此之前我们声明了a = b;(从右到左规则,right-to-left rule)。
运行结果如下:
4,7
4.1.2 数学运算符
Rust语言支持5种数学运算符,分别为加(+)、减(−)、乘(*)、除(/)、取模(%),括号里的符号就是数学运算符号。加减乘除运算想必大家都很了解,它们和一般的数学运算符没有区别。
唯一你可能不太熟悉的是用百分号(%)表示的取模运算(Module)。取模运算是取两个整数相除的余数。例如,如果我们写a = 11 % 3;,变量a的值将会为2,因为2是11除以3的余数。比如:
fn main() {let mut a:i32;let mut b:i32;let mut c:i32; a = 11 % 3; // 取模运算得a为2b = 4+a; //加法运算得b为6c =(a+b)/2; //除法运算得c为4 println!("{},{},{}",a,b,c);}
输出结果:
2,6,4
4.1.3 组合运算符
Rust以书写简练著称,其一大特色就是这些组合运算符(+=、−=、*=、/=及其他),这些运算符使得只用一个基本运算符就可以改写变量的值:
value += increase; 等同于 value = value + increase;
比如:
- a −= 5; 等同于 a = a − 5;。
- a /= b; 等同于 a = a / b;。
- price *= units + 1; 等同于price = price * (units + 1);。
其他运算符以此类推。下面来看一个组合运算符的例子,代码如下:
fn main() {let mut a:i32;let mut b:i32;let mut c:i32; a = 11 % 3; // a:2b = 4+a; // b:6c =(a+b)/2; //c:3 a+=c; b*=a;c/=2; println!("{},{},{}",a,b,c);}
结果输出:
6,6,4
值得庆幸的是,Rust 语言不支持自增运算符(++)和自减运算符(--),因此本节绝对不会出现类似于a+++++i这样让人血压升高的语句。其实,编程语言由于是给人用的,一定要考虑到人的局限性(就是面对复杂事物容易出错),所以编程语言一定要简单明了,Rust去掉了++和--,相对于C语言而言,绝对是个进步,可以从源头上尽可能防止人类出错。
4.1.4 关系运算符
我们用关系运算符来比较两个表达式,关系运算的结果是一个布尔值,即它的值只能是true或false。例如,我们想通过比较两个表达式来看它们是否相等,或一个值是否比另一个值大。表4-1所示为Rust的关系运算符。
示例代码如下:
fn main() {let mut a:bool;let mut b:bool;let mut c:bool;a=(7!=5);b = (100<=99);c=(6==6);println!("{},{},{}",a,b,c);}
运行结果:true,false,true。
除使用数字常量外,我们也可以使用任何有效表达式,包括变量。比如下列代码:
fn main() {let mut a:i32;let mut b:i32;let mut c:i32;a=2;b=3;c=6;println!("{},{},{}",(a == 5),(a*b >= c),(b+4 > a*c));}
输出结果:false,true,false。(a*b >= c)返回true是因为它实际是(2*3 >= 6),(b+4 > a*c)返回false因为它实际是(3+4 > 2*6)。
值得注意的是,运算符=(单个等号)不同于运算符==(两个等号),前者是赋值运算符(将等号右边的表达式值赋给左边的变量);后者(==)是一个判断等于的关系运算符,用来判断运算符两边的表达式是否相等。
4.1.5 逻辑运算符
运算符!等同于boolean运算NOT(取非),它只有一个操作数(Operand),写在它的右边。它做的唯一工作就是取该操作数的反面值,也就是说如果操作数值为真(true),那么运算后值变为假(false),如果操作数值为假(false),则运算结果为真(true)。它就好像是取与操作数相反的值。例如:
- !(5 == 5)返回false,因为它右边的表达式(5 == 5)为真(true)。
- !(6 <= 4)返回true,因为(6 <= 4)为假(false)。
- !true返回假(false)。
- !false返回真(true)。
大家如果不信,可以用下列代码直接输出看看结果:
println!("{},{},{},{}",!(5 == 5),!(6 <= 4),!true,!false);
逻辑运算符&&和||用来计算两个表达式而获得一个结果值。它们分别对应逻辑运算中的与运算(AND)和或运算(OR)。它们的运算结果取决于两个操作数的关系,如表4-2所示。
例如:
- ( (5 == 5) && (3 > 6) )返回false ( true && false )。
- ( (5 == 5) || (3 > 6))返回true ( true || false )。
大家如果不信,可以用下列代码直接输出看看结果:
println!("{},{}",( (5 == 5) && (3 > 6) ) ,( (5 == 5) || (3 > 6)));
4.1.6 位运算符
位运算符以比特位改写变量存储的数值,也就是改写变量值的二进制表示。Rust的位运算符如表4-3所示。
下面的范例演示上面提到的所有位运算符。
fn main() {let a:i32 = 2; // 二进制表示为 0 0 0 0 0 0 1 0let b:i32 = 3; // 二进制表示为 0 0 0 0 0 0 1 1let mut result:i32;result = a & b;println!("(a & b) => {} ",result);result = a | b;println!("(a | b) => {} ",result) ;result = a ^ b;println!("(a ^ b) => {} ",result);result = !b;println!("(!b) => {} ",result);result = a << b;println!("(a << b) => {}",result);result = a >> b;println!("(a >> b) => {}",result);}
输出结果如下:
(a & b) => 2(a | b) => 3(a ^ b) => 1(!b) => -4(a << b) => 16(a >> b) => 0
4.1.7 变量类型转换运算符
变量类型转换运算符可以将一种类型的数据转换为另一种类型的数据。在Rust中,可以使用关键字as进行类型转换,as 运算符有点像C中的强制类型转换,区别在于,它只能用于原始类型(i32、i64、f32、f64、u8、u32、char等类型),并且它是安全的。注意,不同的数值类型是不能进行隐式转换的。比如:
let b: i64 = iNum; //iNum是一个i32类型的变量
会出现编译错误,提示无法进行类型转换。这时可以使用as 进行转换,比如:
fn main() {let mut iNum:i32; let mut b:i64; iNum=100;b = iNum as i64;print!("{}",b);}
输出结果:100。
为什么as是安全的?尝试以下代码:
b = iNum as char;
编译器报错:
error[E0604]: only `u8` can be cast as `char`, not `i32`
可见在不相关的类型之间,Rust 会拒绝转换,这样避免了运行时错误。
4.1.8 运算符的优先级
当多个操作数组成复杂的表达式时,我们可能会疑惑哪个运算先被计算,哪个后被计算。例如以下表达式:
a = 5 + 7 % 2
我们可以怀疑它实际上表示:a = 5 + (7 % 2) 结果为6,还是 a = (5 + 7) % 2 结果为0?
正确答案为第一个,结果为6。每一个运算符都有一个固定的优先级,不仅是数学运算符(我们可能在学习数学的时候已经很了解它们的优先顺序了),所有在Rust中出现的运算符都有优先级。从最高级到最低级,运算符的优先级按表4-4排列。
以下是简单的示例:
fn main() {//二元计算操作println!("1 + 2 = {}", 1u32 + 2);println!("1 - 2 = {}", 1i32 - 2);//逻辑操作println!("true AND false is {}", true && false);println!("true OR false is {}", true || false);println!("NOT true is {}", !true);//位运算操作println!("0011 AND 0101 is {:04b}", 0b0011u32 & 0b0101);println!("0011 OR 0101 is {:04b}", 0b0011u32 | 0b0101);println!("0011 XOR 0101 is {:04b}", 0b0011u32 ^ 0b0101);println!("1 << 5 is {}", 1u32 << 5);println!("0x80 >> 2 is 0x{:x}", 0x80u32 >> 2);}
运行结果如下:
1 + 2 = 31 - 2 = -1true AND false is falsetrue OR false is trueNOT true is false0011 AND 0101 is 00010011 OR 0101 is 01110011 XOR 0101 is 01101 << 5 is 320x80 >> 2 is 0x20
所有这些运算符的优先级顺序可以通过使用一对圆括号“()”来控制,而且更易读懂,示例如下:
a = 5 + 7 % 2;
根据我们想要实现的计算不同,可以写成:
a = 5 + (7 % 2);
效果和a = 5 + 7 % 2;一样,因为%的优先级比+高,所以加不加括号没什么区别。如果要先计算5+7,则可以这样:
a = (5 + 7) % 2;
此时最终计算结果就不同了。所以如果想写一个复杂的表达式而不敢肯定各个运算的执行顺序,那么就加上括号。这样可以使代码更易读懂。
相关文章:

Rust运算符
【图书介绍】《Rust编程与项目实战》-CSDN博客 《Rust编程与项目实战》(朱文伟,李建英)【摘要 书评 试读】- 京东图书 (jd.com) https://blog.csdn.net/brucexia/category_12779443.html 前面已经学习了变量和常量,本节开始对它们进行操作,…...

Oracle rman 没有0级时1级备份和0级大小一样,可以用来做恢复 resetlogs后也可以
文档说了 full backup 不能 用于后续的level 1,没说level 1没有level 0 是不是level 1就是level 0? 1级备份变0级的原因 及 Enabling Change Tracking生效没有-CSDN博客 这个文档说明1级备份时没有找到0级就是0级备份,可以用来完整恢复的。…...

idea中配置Translation插件完成翻译功能
文章目录 idea下载插件配置有道云阿里云百度翻译开放平台 idea下载插件 idea中安装Translation插件 使用方法:右下角选择翻译引擎,鼠标选中想翻译的部分,右键翻译即可 之前一直用的微软的翻译,不需要配置,但是最近微软…...
如何看待:低代码开发平台的兴起无需经验?
在当今快速发展的技术时代,软件开发的需求日益增长,而专业开发人员的数量却远远跟不上需求的步伐。为了解决这一矛盾,低代码开发平台应运而生,它通过提供可视化的开发环境和拖拽式的编程方式,使得没有编程经验的用户也…...

OpenCV-轮廓检测
文章目录 一、简介1. 意义2.具体步骤 二、代码实现三、总结 一、简介 1. 意义 在OpenCV中,轮廓检测是图像处理中一个非常重要的环节,它允许我们识别图像中的形状。这个过程通常涉及几个步骤:读取图像、转换为灰度图、应用阈值处理ÿ…...

vue页面使用自定义字体
一、准备好字体文件 一般字体问价格式为 .tff,可以去包图网等等网站去下载,好看的太多了!!! 下载下来就是单个的 .tff文件,下载下来后可以进行重命名,但是不要改变他的后缀名,我把他…...
C++——list常见函数的使用和模拟实现(2)
在list的上一篇博客里实现了list基本的初始化、插入数据、删除数据的基本功能,这些功能的实现方式只是在原先链表的实现里加入了模版而已,但是list作为一个容器,它还有一个基础的东西——迭代器。list的迭代器和之前实现的string和vector很大…...
C 标准库 - `<float.h>`
C 标准库 - <float.h> 概述 <float.h> 是 C 标准库中的一个头文件,它定义了与浮点数类型相关的宏。这些宏提供了关于浮点数的属性信息,如精度、最小和最大值、以及舍入误差等。这个头文件对于需要精确控制浮点数行为的程序非常有用&#x…...

【机器人工具箱Robotics Toolbox开发笔记(二)】Matlab中机器人工具箱的下载与安装
Matlab机器人工具箱(Robotics Toolbox)可从Peter Corke教授提供的网站上免费下载。网址为:http://www.petercorke.com/Robotics_Toolbox.html。 图1 网站所提供的机器人工具箱版本 在Downloading the Toolbox栏目中单击here按钮进入下载页面,然后在该页面中填写国家、组织…...

ROS2 Nav2 - Smac 规划器
系列文章目录 前言 SmacPlanner 是 Nav2 Planner 服务器的插件。它目前包括 3 个不同的插件: SmacPlannerHybrid:高度优化的完全可重新配置的 Hybrid-A* 实现,支持 Dubin 和 Reeds-Shepp 模型(足式、阿克曼和汽车模型)…...

LabVIEW环境中等待FPGA模块初始化完成
这个程序使用的是LabVIEW环境中的FPGA模块和I/O模块初始化功能,主要实现等待FAM(Field-Programmable Gate Array Module,FPGA模块)的初始化完成,并处理初始化过程中的错误。让我们逐步分析各部分的功能: 1.…...

手机TF卡格式化后数据恢复:方法、挑战与预防措施
在现代生活中,手机已经成为我们不可或缺的一部分,而TF卡(即MicroSD卡)作为手机存储的扩展,更是承载了我们大量的重要数据。然而,不慎的格式化操作往往导致数据丢失,给用户带来不…...

ceph对象存储使用的一些思考
导言 我在某司做对象存储约4年时间,作为研发人员,接触过大量的市场项目,对国内市场上对对象存储的使用有一些了解和思考。本文主要是对本人经历的过往对象存储项目中发现的一些问题进行总结。 背景如下: 基于ceph版本进行开发并进…...

单词排序C++实现
代码如下: #include<iostream> #include<string> #include<fstream> #include<map> #include<iomanip> #include<algorithm> #include<vector>int read_file(std::map<std::string,int> &map_words) {std::st…...

828华为云征文 | Flexus X 实例服务器网络性能深度评测
引言 随着互联网应用的快速发展,网络带宽和性能对云服务器的表现至关重要。在不同的云服务平台上,即便配置相同的带宽,实际的网络表现也可能有所差异。因此,了解并测试服务器的网络性能变得尤为重要。本文将以华为云X实例服务器为…...

STL —heap算法源码刨析 make_heap、push_heap、pop_heap、sort_heap操作分析
STL —heap算法源码刨析 heap算法概述push_heap 插入元素pop_heap 取出根节点元素sort_heap 按极值存放元素make_heap 将一段现有数据构造成heap程序测试 heap算法概述 heap的内部是一个完全二叉树,将极值存放在根节点。这个里的极值可分为最大值、最小值。根据极值…...

走进低代码表单开发(一):可视化表单数据源设计
在前文,我们已对勤研低代码平台的报表功能做了详细介绍。接下来,让我们深入探究低代码开发中最为常用的表单设计功能。一个完整的应用是由众多表单组合而成的,所以高效的表单设计在开发过程中起着至关重要的作用。让我们一同了解勤研低代码开…...

简单好用的OCR API
现如今,越来越多的科技产品可以帮助我们改善和提高相应的工作效率。OCR技术的出现,提高了人们的工作效率,其应用领域及其广泛。就拿应用了OCR技术的翔云文档识别服务来说,只需上传文档图片便可自动识别并返回文档中相应的内容。翔…...
c++的拷贝构造函数和赋值函数
拷贝构造函数和赋值函数 什么是拷贝构造 是一种特殊构造函数,如果没有显式的实现,编译器就会自动生成。 class 类名 { public:// 拷贝构造类名(const 类名& that){} }; 什么时候会调用拷贝构造 当使用一个类对象给另一个新的类对象初始化时&…...

什么自动猫砂盆才适合旅游党?4个选购技巧统统告诉你!
有没有能让我们防夹3天不在家都不用担心猫咪铲屎问题的方法?当然有了!自动猫砂盆就是最好的选择,要知道,有个好用合适的自动猫砂盆在家的话,根本不用担心生虫发臭的问题出现,因为自动猫砂盆能及时感应到猫咪…...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
Rapidio门铃消息FIFO溢出机制
关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系,以下是深入解析: 门铃FIFO溢出的本质 在RapidIO系统中,门铃消息FIFO是硬件控制器内部的缓冲区,用于临时存储接收到的门铃消息(Doorbell Message)。…...