网站运营内容方案,素材网网站建设,理发培训专业学校,无锡制作网站1.Rust数据类型
在 Rust 中, 每一个值都属于某一个 数据类型#xff08;data type#xff09;, 这告诉 Rust 它被指定为何种数据#xff0c;以便明确数据处理方式。我们将看到两类数据类型子集#xff1a;标量#xff08;scalar#xff09;和复合#xff08;compounddata type, 这告诉 Rust 它被指定为何种数据以便明确数据处理方式。我们将看到两类数据类型子集标量scalar和复合compound。
Rust是静态类型statically typed语言也就是说在编译时就必须知道所有变量的类型。根据值及其使用方式编译器通常可以推断出我们想要用的类型。当多种类型均有可能时必须增加类型注解像这样
let u_number: u32 42.parse().expect(Not a number!);
如果不像上面的代码这样添加类型注解 : u32Rust 会显示如下错误这说明编译器需要我们提供更多信息来了解想要的类型 2.标量类型
标量scalar类型代表一个单独的值。Rust 有四种基本的标量类型整型、浮点型、布尔类型和字符类型。
2.1 整型
整数 是一个没有小数部分的数字。下面表格展示了 Rust 内建的整数类型。我们可以使用其中的任一个来声明一个整数值的类型。
长度有符号无符号8-biti8u816-biti16u1632-biti32u3264-biti64u64128-biti128u128archisizeusize
每一个变体都可以是有符号或无符号的并有一个明确的大小。有符号 和 无符号 代表数字能否为负值换句话说这个数字是否有可能是负数有符号数或者永远为正而不需要符号无符号数。这有点像在纸上书写数字当需要考虑符号的时候数字以加号或减号作为前缀然而可以安全地假设为正数时加号前缀通常省略。有符号数以补码形式存储。
每一个有符号的变体可以储存包含从 -(2n - 1) 到 2n - 1 - 1 在内的数字这里 n 是变体使用的位数。所以 i8 可以储存从 -(27) 到 27 - 1 在内的数字也就是从 -128 到 127。无符号的变体可以储存从 0 到 2n - 1 的数字所以 u8 可以储存从 0 到 28 - 1 的数字也就是从 0 到 255。
另外isize 和 usize 类型依赖运行程序的计算机架构64 位架构上它们是 64 位的32 位架构上它们是 32 位的。
可以使用以下表格的任何一种形式编写数字字面值。请注意可以是多种数字类型的数字字面值允许使用类型后缀例如 57u8 来指定类型同时也允许使用 _ 做为分隔符以方便读数例如1_000它的值与你指定的 1000 相同。
数字字面值例子Decimal (十进制)98_222Hex (十六进制)0xffOctal (八进制)0o77Binary (二进制)0b1111_0000Byte (单字节字符)(仅限于u8)bA
那么该使用哪种类型的数字呢如果拿不定主意Rust 的默认类型通常是个不错的起点数字类型默认是 i32。isize 或 usize 主要作为某些集合的索引。
2.2 浮点型
Rust 也有两个原生的 浮点数floating-point numbers类型它们是带小数点的数字。Rust 的浮点数类型是 f32 和 f64分别占 32 位和 64 位。默认类型是 f64因为在现代 CPU 中它与 f32 速度几乎一样不过精度更高。所有的浮点型都是有符号的。
以下是浮点数的代码例子
fn main() {let x 2.0; // f64let y: f32 3.0; // f32
}
浮点数采用 IEEE-754 标准表示。f32 是单精度浮点数f64 是双精度浮点数。
2.3 布尔型
正如其他大部分编程语言一样Rust 中的布尔类型有两个可能的值true 和 false。Rust 中的布尔类型使用 bool 表示。
布尔型的使用例子如下:
fn main() {let t true;let f: bool false;
}
使用布尔值的主要场景是条件表达式例如 if 表达式。
2.4 字符类型
Rust 的 char 类型是语言中最原生的字母类型。下面是一些声明 char 值的例子
fn main() {let c z;let z: char ℤ;let heart_eyed_cat ;
}
注意我们用单引号声明 char 字面量而与之相反的是使用双引号声明字符串字面量。Rust 的 char 类型的大小为四个字节 (four bytes)并代表了一个 Unicode 标量值Unicode Scalar Value这意味着它可以比 ASCII 表示更多内容。在 Rust 中带变音符号的字母Accented letters中文、日文、韩文等字符emoji绘文字以及零长度的空白字符都是有效的 char 值。Unicode 标量值包含从 U0000 到 UD7FF 和 UE000 到 U10FFFF 在内的值。不过“字符” 并不是一个 Unicode 中的概念所以人直觉上的 “字符” 可能与 Rust 中的 char 并不符合。
3.复合类型
复合类型Compound types可以将多个值组合成一个类型。Rust 有两个原生的复合类型元组tuple和数组array。
3.1 元组类型
元组是一个将多个其他类型的值组合进一个复合类型的主要方式。元组长度固定一旦声明其长度不会增大或缩小。
我们使用包含在圆括号中的逗号分隔的值列表来创建一个元组。元组中的每一个位置都有一个类型而且这些不同值的类型也不必是相同的。例子如下:
fn main() {let tup: (i32, f64, u8) (500, 6.4, 1);
}
tup 变量绑定到整个元组上因为元组是一个单独的复合元素。为了从元组中获取单个值可以使用模式匹配pattern matching来解构destructure元组值像这样
fn main() {let tup (500, 6.4, 1);
let (x, y, z) tup;
println!(The value of y is: {y});
}
程序首先创建了一个元组并绑定到 tup 变量上。接着使用了 let 和一个模式将 tup 分成了三个不同的变量x、y 和 z。这叫做 解构destructuring因为它将一个元组拆成了三个部分。最后程序打印出了 y 的值也就是 6.4。
我们也可以使用点号.后跟值的索引来直接访问它们。例如
fn main() {let x: (i32, f64, u8) (500, 6.4, 1);
let five_hundred x.0;
let six_point_four x.1;
let one x.2;
}
这个程序创建了一个元组x然后使用其各自的索引访问元组中的每个元素。跟大多数编程语言一样元组的第一个索引值是 0。
不带任何值的元组有个特殊的名称叫做 单元unit 元组。这种值以及对应的类型都写作 ()表示空值或空的返回类型。如果表达式不返回任何其他值则会隐式返回单元值。
3.2 数组类型
另一个包含多个值的方式是 数组array。与元组不同数组中的每个元素的类型必须相同。Rust 中的数组与一些其他语言中的数组不同Rust 中的数组长度是固定的。
我们将数组的值写成在方括号内用逗号分隔
fn main() {let a [1, 2, 3, 4, 5];
}
当要在栈stack而不是在堆heap上为数据分配空间或者是想要确保总是有固定数量的元素时数组非常有用。但是数组并不如 vector 类型灵活。vector 类型是标准库提供的一个 允许 增长和缩小长度的类似数组的集合类型。当不确定是应该使用数组还是 vector 的时候那么很可能应该使用 vector。
然而当你确定元素个数不会改变时数组会更有用。例如当你在一个程序中使用月份名字时你更应趋向于使用数组而不是 vector因为你确定只会有 12 个元素。
let months [January, February, March, April, May, June, July,August, September, October, November, December];
可以像这样编写数组的类型在方括号中包含每个元素的类型后跟分号再后跟数组元素的数量。
let a: [i32; 5] [1, 2, 3, 4, 5];
这里i32 是每个元素的类型。分号之后数字 5 表明该数组包含五个元素。
你还可以通过在方括号中指定初始值加分号再加元素个数的方式来创建一个每个元素都为相同值的数组
let a [3; 5];
变量名为 a 的数组将包含 5 个元素这些元素的值最初都将被设置为 3。这种写法与 let a [3, 3, 3, 3, 3]; 效果相同但更简洁。
数组是可以在栈 (stack) 上分配的已知固定大小的单个内存块。可以使用索引来访问数组的元素像这样
fn main() {let a [1, 2, 3, 4, 5];
let first a[0];let second a[1];
}
在这个例子中叫做 first 的变量的值是 1因为它是数组索引 [0] 的值。变量 second 将会是数组索引 [1] 的值 2。
如果我们访问数组结尾之后的元素会发生什么呢比如执行以下代码
use std::io;
fn main() {let a [1, 2, 3, 4, 5];
println!(Please enter an array index.);
let mut index String::new();
io::stdin().read_line(mut index).expect(Failed to read line);
let index: usize index.trim().parse().expect(Index entered was not a number);
let element a[index];
println!(The value of the element at index {index} is: {element});
}
此代码编译成功。如果运行此代码并输入 0、1、2、3 或 4程序将在数组中的索引处打印出相应的值。如果你输入一个超过数组末端的数字如 10你会看到这样的输出 程序在索引操作中使用一个无效的值时导致 运行时 错误。程序带着错误信息退出并且没有执行最后的 println! 语句。当尝试用索引访问一个元素时Rust 会检查指定的索引是否小于数组的长度。如果索引超出了数组长度Rust 会 panic这是 Rust 术语它用于程序因为错误而退出的情况。这种检查必须在运行时进行特别是在这种情况下因为编译器不可能知道用户在以后运行代码时将输入什么值。
这是第一个在实战中遇到的 Rust 安全原则的例子。在很多底层语言中并没有进行这类检查这样当提供了一个不正确的索引时就会访问无效的内存。通过立即退出而不是允许内存访问并继续执行Rust会让程序员避开此类错误。
4.总结
在本篇文章中,我们学习了Rust的基本数据类型,包括:整型、浮点型、布尔型、字符串、元祖类型和数组类型。
在下篇文章中,我们将一起学习Rust的函数和控制流。