《Rust编程与项目实战》(朱文伟,李建英)【摘要 书评 试读】- 京东图书 (jd.com)
3.3.1 常量的定义
常量和变量是高级程序设计语言中数据的两种表现形式。这里我们先介绍常量,常量是指程序运行过程中值始终不变的量。常量的特点是一旦被定义就不能被修改或重新定义。常量可以是一个具体的数值或一个数学表达式。例如,数学中的圆周率π,就是一个常量,它的取值是固定且不能被改变的,又如1、2、1000、5.88等数值也是常量。
在Rust中,常量分为直接常量和const常量。
3.3.2 直接常量
直接常量是指由具体数据直接表示的形式,分为整数常量、实数常量、字符常量和字符串常量。也就是说,直接常量从字面上就可以识别,因此也称为“字面常量”。直接常量通常可以分为以下3类。
1. 数值常量
顾名思义,数值常量就是由数字构成的常量,数值常量就是数学中的常数。在Rust语言中,数值常量可以分为整数型常量和实数型常量,如100、250、1000这种整数在Rust语言中叫作整数型常量,即整型常量(整常数);如1.22、3.142等带有小数点的称为实数型常量,即实型常量(实常数)。
实数型常量又可以用两种形式表现,一种就是我们经常用的十进制小数形式,如123.456、23.56等,但是由于计算机的内存限制和计算规则以及工程科学中对于数值计算的要求,经常会用科学记数法来表示实数,也就是指数形式,如12.34e3(代表12.34乘以10的3次方)。在Rust语言中规定用e/E来代表以10为底的指数,在e的前面必须有数字,e的后面必须为整数。
2. 字符常量
字符常量即为用字符构成的常量,有以下两种表现形式。
1)普通字符
普通字符用单引号引起来,但单引号只是表示界限,单引号中的字符才是普通字符,而且单引号中只能有一个字符,比如'a'、'B'、'+'、'1'、'?'、'中'等,像'12a'、'tt'就不是合法的字符。在Rust中,字符数据在计算机中是以Unicode值存储的,因此Unicode值能对应的字符都是Rust的字符常量,包括空格、数字0~9、小写字母a~z、大写字母A~Z和标点符号、中文/日文/韩文、emoji表情符号、各种中英文标点符号、算式符号(比如加、减、乘、除)等。
2)转义字符
转义字符这是Rust语言自己定义的字符,是一种控制字符,以字符\开头,如经常使用的'\n'就代表换行,'\t'代表空格,如表3-1所示。
学过C语言的同学,这里要注意一下\r和\n,在C语言中,这两个转义字符的作用是不同的,前者是回车,表示输入指针回到当前行行首,也就是\r后面的内容将在当前行首输出。比如下列C 代码:
printf("aaa\rbbb");
VC下输出的是bbb,因为\r表示回到当前行行首,所以后面的bbb就覆盖了缓冲区中的aaa,最终的打印结果也是bbb。
而在Rust下,\r的效果同\n,如下列代码:
println!("aaa\rbbb\nccc");
输出结果如下:
aaa
bbb
ccc
3. 字符串常量
顾名思义,就是一串字符常量的组合,但需要用一对英文双引号将这些字符引起来,比如"man"、"123boy"、"tt_88_bag"等。
let x= "man"; //这里,"man"就是字符串
println!("{x}"); //输出man
注意,字符串常量需要用双引号引起来。字符串常量也称字符串字面值,它实际上存储在可执行程序的只读内存段中。
3.3.3 const常量
直接常量从字面形式上就可以识别,因此称为“字面常量”或“直接常量”,它们是没有名字的不变量。但有的时候,直接将这些不变量放在代码中会显得有些啰唆,比如圆周率3.14,如果代码中多处地方用到圆周率,那么每个地方都要写3.14,这样代码看上去就不是很简洁。这个时候,如果用一个符号(比如PI)来代替3.14,就简洁多了。而且,如果我们的代码以后要采用保留3位小数的圆周率,那么就要将每个3.14都改为3.141,这岂不是很麻烦!
因此,Rust提供了const关键字,让我们可以用它来定义一个有名称的常量,const常量在Rust中经常简称为常量。但要注意,定义const常量时需要明确指定常量名称和数据类型,关于数据类型,我们后面会将讲到。定义常量时,必须进行初始化,比如:
const PI:f32=3.14
其中,PI就是常量的名称,f32是常量PI的数据类型,表示32位的实数类型,3.14是常量绑定的值。以后代码中需要用3.14的地方,都可以用PI来代替。这样有个好处,如果以后程序中要使用三位小数的圆周率,那么只需要将PI的定义改为:
const PI:f32=3.141
这样程序代码中有PI的地方都代表3.141,非常方便。
定义常量要注意以下几点:
(1)定义常量时命名规则一般是全部大写(如NUM),非强制,否则会有警告。
(2)const定义的常量在程序运行过程中只有一份备份。
(3)常量的赋值只能是常量表达式/数学表达式,也就是说必须是在编译期就能计算出的值,如果需要在运行时才能得出结果的值(比如函数),则不能赋值给常量表达式。
(4)对于常量是不允许出现重复的定义的。例如下面的代码就会报错:
fn test_define_same_const_variable(){
const NUM:i32=100;
const NUM:f64=200.0; //error[E0428]: the name `NUM` is defined multiple times
}
总之,使用符号常量有两个优点:一个是提高可读性,比如在程序中使用PI,大概就知道代表圆周率;另一个是在程序中多处使用同一个常量时,能做到一改全改。
const常量将在编译期间直接以硬编码的方式内联(Inline)插入使用常量的地方。所谓内联,即将它代表的值直接替换到使用它的地方。比如,定义了const常量ABC=33,在第100行和第300行处都使用了常量ABC,那么在编译期间,会将33硬编码到第100行和第300行处。
Rust中的const常量不仅默认不可变,而且自始至终不可变,因为常量在编译完成后,已经确定了它的值。