类型,第1部分

"语法"部分中,compute的输入参数类型为 u32。让我们来解开这个是什么意思。

基本类型

u32是Rust的基本类型之一。基本类型是语言最基本的构建模块。它们内置于语言本身中——也就是说,它们不是由其他类型定义的。

你可以组合这些基本类型来创建更复杂的类型。我们很快就会看到怎么做。

整数

具体来说,u32是一个无符号32位整数

整数是一个不包含小数部分的数字。例如,1是一个整数,而1.2不是。

有符号与无符号

整数可以是有符号无符号的。无符号整数只能表示非负数(即0或更大)。有符号整数可以表示正数和负数(例如-112等)。

u32中的u代表无符号。等效的有符号整数类型是i32,其中i代表整数(即任何整数,正数或负数)。

位宽

u32中的32是指用于在内存中表示该数字的位数1。位数越多,可以表示的数字范围就越大。

Rust支持多个位宽的整数:8163264128

用32位,u32可以表示从02^32 - 1(又称u32::MAX)的数字。 用相同的位数,有符号整数(i32)可以表示从-2^312^31 - 1的数字(即从i32::MINi32::MAX)。 i32的最大值小于u32的最大值,因为一个位用于表示数字的符号。 更多关于有符号整数在内存中是如何表示的详细信息,请查看二补码表示。

总结

将有符号/无符号和位宽两个变量结合,我们得到以下整数类型:

位宽有符号无符号
8位i8u8
16位i16u16
32位i32u32
64位i64u64
128位i128u128

字面值

字面值是在源代码中表示固定值的符号。例如,42是Rust中表示四十二这个数字的字面值。

字面值的类型注解

但是Rust中所有值都有类型,所以...42是什么类型呢?

Rust编译器会尝试根据使用环境来推断字面值的类型。如果你不提供任何上下文信息,编译器将默认为i32整数字面值。如果你想使用其他类型,你可以在字面值后面添加所需的整数类型作为后缀——例如2u64表示一个显式声明为u64类型的2。

字面值中的下划线

你可以使用下划线_来提高大数字的可读性。例如,1_000_0001000000是相同的。

算术运算符

Rust支持以下用于整数的算术运算符2:

  • +用于加法
  • -用于减法
  • *用于乘法
  • /用于除法
  • %用于取余

这些运算符的优先级和结合性规则与数学中的相同。你可以使用括号来覆盖默认的优先级,例如2 * (3 + 4)

⚠️ 警告

当用于整数类型时,除法运算符/执行整数除法。 换句话说,结果会被截断为0。例如,5 / 2的结果是2,而不是2.5

没有自动类型强制转换

正如我们在上一个练习中讨论的,Rust是一种静态类型语言。具体来说,Rust对类型强制转换非常严格。即使转换是无损的,它也不会自动将一个值从一种类型转换为另一种类型3,你必须显式地进行转换。

例如,你不能将一个u8值赋给类型为u32的变量,即使所有的u8值都是有效的u32值:

#![allow(unused)]
fn main() {
let b: u8 = 100;
let a: u32 = b;
}

它会抛出编译错误:

error[E0308]: mismatched types
  |
3 |     let a: u32 = b;
  |            ---   ^ expected `u32`, found `u8`
  |            |
  |            expected due to this
  |

我们将在本课程的后面看到如何在不同类型之间进行转换。

参考资料

本节的练习位于 exercises/02_basic_calculator/01_integers

进一步阅读

好的,以下是这些内容的翻译:

1

位是计算机中最小的数据单位。它只能有两个值:0或1。

2

Rust不允许你定义自定义运算符,但它让你可以控制内置运算符的行为。在我们讨论了特征之后,将会在本课程的后面讨论运算符重载。

3

对于这个规则也有一些例外,主要与引用、智能指针和人体工程学有关。我们将稍后介绍这些内容。目前,"所有转换都是显式的"这个心智模型将为你提供很好的服务。