Rust中的变量的声明和定义

摘要:
变量的声明和定义Rust中的合法标识符必须由数字、字母和下划线组成,并且不能以数字开头。let in变量声明的使用也借鉴了函数语言的思想。Let表示绑定的含义,这意味着变量名和内存绑定在一个层中。在Rust中,声明局部变量并初始化它们的语句通常称为“变量绑定”。这里强调的是“绑定”的含义,它与C++/C中的“赋值初始化语句”不同。
变量的声明和定义

Rust中合法的标识符(包括变量名、函数名、triat名等)必须由数字、字母、下划线组成,而且不能以数字开头。这个和很多语言都是一样的。Rust将来也会允许其他Unicode字符作为标识符,还有raw identifier功能,这样可以使关键字作为标识符,比如r#self,这个用途在FFI中最多。

变量的声明: let variable : i32 = 100; , 在rust中采用的变量的声明方式不同于以往语言的声明方式,这里先看变量的声明, 变量的声明时,是变量的名字先在前,而变量的类型在后面,let variable: i32;就是这个样子。

这样变量声明的好处是,对于语法分析来说分析更为方便,并且在变量声明语句中最为重要的是变量的名字,将变量名提前突出显式变量名的重要性,对于类型是变量名的附加说明,可以通过上下文推导出变量的类型,当让rust的自动类型推导具有局限性,对于不能推导出来的类型,需要手动添加类型说明。

变量声明中的let的使用也是借鉴了函数式语言的思想,let表明的是绑定的含义,表示的是将变量名和内存作了一层绑定关系。在Rust中,一般把声明的局部变量并初始化的语句称为”变量绑定“, 这里强调的是”绑定“的含义,这里和C++/C中的”赋值初始化语句有所不同。

变量定义的一些问题

Rust中,每个变量必须被合理初始化之后才能被使用,使用未初始化变量这样的错误,在rust中是不可能出现的。

检查是否声明初始化变量

刚刚上面的let variable : i32;这个是声明,而没有给变量赋值,这个在别的语言中可能是行的通的,但是在rust中,编译器直接报错(如果在后面使用这个为赋值(定义)的变量, Rust编译器会对代码作基本的静态分支流程分析,确保变量在使用之前一定被初始化,variable没有绑定任何值,这样的代码会引起很多内存不安全的问题,比如计算结果非预期、程序崩溃,所以Rust编译器必须报错。

1 let variable: i32;
2 println!("variable  = {}", variable); // error[E0381]: use of possibly unintialized 'variable' 

检测分支流程是否产生为初始化变量

Rust编译器的静态分支流程分析比较严格。

1 fn main() {
2     let x: i32;
3     if true {
4         x = 1;
5     } else {
6         x = 2;
7     }
8     println!("x = {}", x);
9 }

这里的if分支的所有情况都给变量x绑定了值,所以它可以运行。但是如果去掉else分支,编译器就会报错:

error: use of possibly unintialized variable : 'x'
println!("x = {}", x);

从这里可以看到编译器已经检查出来变量x没有被正确的初始化。去掉else分支后,编译器的静态分支流程分析判断出在if表达式之外的println!也用到了变量x,但并未有绑定任何值得行为。编译器的静态分支流程分析并不能识别if表达式中的条件是true, 所以他要检查所有分支的情况。(这个在程序设计语言领域中有专门去做研究的,比如软件的静态分析,一些参考材料:南京大学的软件分析课程)

要是在把println!语句也去掉的话,则可以正常编译运行,这是因为if表达式之外再也没有任何地方使用变量x, 在唯一使用到x的if表达式中已经绑定了值,所以编译正常。

 1 // 有一个例子
 2 fn test(condition: bool ){
 3     let x: i32; //声明x
 4     if condition {
 5         x = 1; //初始化x,这里是初始化
 6         println!("{}", x); 
 7     }
 8     // 如果条件不满足,x没有被初始化
 9 
10     //但是没有关系,只要这里不使用x就没有事
11 }

检测循环中是否产生未初始化变量

当循环中使用break关键字的时候,break会将分支中的变量值返回。

 1 fn main() {
 2     let x : i32;
 3     loop {
 4         if true {
 5             x = 2;
 6             break;
 7         }
 8     }
 9     println!("{}", x);// 2
10 }

Rust编译器的静态分支流程分析知道,break会将x的值返回,这样loop循环之外println!可以正常打印x的值

空数组或向量可以初始化变量

当变量绑定空的数组或向量时,需要显式制定类型,否则编译器无法推断其类型。

1 fn main() {
2     let a: Vec<i32> = vec![];
3     let b: [i32; 0] = [];
4 }

要是不加显式类型标注的话,编译器就会报错: error[e0282]: type annotation needed 空数组或向量可以用来初始化变量,但目前暂时无法用于初始化常量或静态变量。

转移了所有权产生了未初始化变量

当将一个已经初始化的变量y绑定给另外一个变量y2时,Rust会把y看做逻辑上的未初始化变量。 这里的y和y2都是移动语义的变量,移动语义的变量会发生所有权的交接,而值语义,就像其他C++语言默认的都是传值。

 1 fn main() {
 2     let x = 42; //原生类型都是值语义,默认存储在栈上,
 3     let y = Box::new(4); //变量是由Box装箱到堆上的, Box::new方法在堆上分配内存返回指针
 4     //并与y绑定,而指针y存储在栈上,
 5     println!("{}", y);
 6     let x2 = x;
 7     let y2 = y;
 8     //println!("{}", y);//发生了所有权的转移,所以这里的变量y可以看做没有未被初始化的变量
 9     //但是如果重新给变量绑定上一个值,变量y依然是可用的,这个过程叫做重新初始化
10 }

免责声明:文章转载自《Rust中的变量的声明和定义》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Sql Server 常用系统存储过程大全极验验证码安装部署教程下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Nginx Rewrite域名及资源重定向

一.正则匹配     1.匹配规则         ^$  标识符匹配后面跟-一个字符串。匹配字符串后将停止对后续的正则表达式进行匹配,如location ^~/images/,在匹配了/images/这个字符串后就停止对后续的正则匹配         =   精准匹配,如location=/,只会匹配url为/的请求         ~   区分大小写的...

Shell脚本1

1Shell编程 Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。 Shell脚本 Shell 脚本(shell script),是一种为 shell 编写的脚本程序。 业界所说的 shell 通常都是指 shell 脚本,(java文本文件)2 Shell环境 Shell...

VxWorks固件分析方法总结

VxWorks固件分析方法总结 最近研究基于VxWorks系统的iot设备的固件分析方法,将学习心得记录于此,以备将来的查询需要。 1.VxWorks是什么? VxWorks是美国WindRiverSystem公司(风河公司)推出的一个RTOS(实时操作系统),凭借良好的持续发展能力、高性能的内核以及友好的用户开发环境,在嵌入式实时操作系统领域占据一席之地...

P6 EPPM R16.1安装与配置指南(二)

 P6 EPPM R16.1安装与配置指南(一) http://www.cnblogs.com/endv/p/5634620.html  P6 EPPM R16.1安装与配置指南(二) 1 环境变量配置 2 3 1 新建系统变量JAVA_HOME SET %JAVA_HOME= 4 变量名:JAVA_HOME 5 变量值:C...

C#命名惯例和规范

C#命名惯例和规范 注记 : Pascal 大小写形式-所有单词第一个字母大写,其他字母小写。 Camel   大小写形式-除了第一个单词,所有单词第一个字母大写,其他字母小写。 类名使用Pascal 大小写形式 public class HelloWorld{ ...} 方法使用Pascal 大小写形式 public class HelloW...

SQL 存储过程入门(变量)

SQL 存储过程入门(变量)(二)上一篇我们讲到了SQL存储过程的基本定义,怎么创建,使用,这篇就来讲一下变量的使用。 变量分文局部变量和全局变量 局部变量是@开头,全局变量是@@开头,这里我们主要讲局部变量,全局变量我们后面再讲。 在c# 语言中,定义一个变量很简单,例如 int i=0; --定义加赋值。 在sql中,定义一个变量需要关键字DECLAR...