类型

Rust有很多类型,让你可以处理数字、字符等。有些类型很简单,有些类型比较复杂,你甚至可以创建自己的类型。

原始类型

Rust有简单的类型,这些类型被称为原始类型(原始=非常基本)。我们将从整数和char(字符)开始。整数是没有小数点的整数。整数有两种类型。

  • 有符号的整数
  • 无符号整数

符号是指+(加号)和-(减号),所以有符号的整数可以是正数,也可以是负数(如+8,-8)。但无符号整数只能是正数,因为它们没有符号。

有符号的整数是 i8, i16, i32, i64, i128, 和 isize

无符号的整数是 u8, u16, u32, u64, u128, 和 usize

i或u后面的数字表示该数字的位数,所以位数多的数字可以大一些。8位=一个字节,所以i8是一个字节,i64是8个字节,以此类推。尺寸较大的数字类型可以容纳更大的数字。例如,u8最多可以容纳255,但u16最多可以容纳65535。而u128最多可以容纳340282366920938463463374607431768211455。

那么什么是isizeusize呢?这表示你电脑的位数。(你的电脑上的位数叫做你电脑的架构)。所以32位计算机上的isizeusize就像i32u32,64位计算机上的isizeusize就像i64u64

整数类型不同的原因有很多。其中一个原因是计算机性能:较小的字节数处理速度更快。例如,数字-10作为i811110110,但作为i12811111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111110110。但这里还有一些其他用法。

Rust中的字符叫做char. 每一个char都有一个数字:字母A是数字65,而字符(中文的 "朋友")是数字21451。这个数字列表被称为 "Unicode"。Unicode对使用较多的字符使用较小的数字,如A到Z,或0到9的数字,或空格。

fn main() {
    let first_letter = 'A';
    let space = ' '; // A space inside ' ' is also a char
    let other_language_char = 'Ꮔ'; // Thanks to Unicode, other languages like Cherokee display just fine too
    let cat_face = '😺'; // Emojis are chars too
}

使用最多的字符的数字小于256,它们可以装进u8。记住,u8是0加上255以内的所有数字,总共256个。这意味着 Rust 可以使用 asu8 安全地 castchar。("把 u8 cast成 char"意味着 "把 u8 假装成 char")

as cast是有用的,因为 Rust 是非常严格的。它总是需要知道类型。 而不会让你同时使用两种不同的类型,即使它们都是整数。例如,这将无法工作:

fn main() { // main() is where Rust programs start to run. Code goes inside {} (curly brackets)

    let my_number = 100; // We didn't write a type of integer,
                         // so Rust chooses i32. Rust always
                         // chooses i32 for integers if you don't
                         // tell it to use a different type

    println!("{}", my_number as char); // ⚠️
}

原因是这样的:

error[E0604]: only `u8` can be cast as `char`, not `i32`
 --> src\main.rs:3:20
  |
3 |     println!("{}", my_number as char);
  |                    ^^^^^^^^^^^^^^^^^

幸运的是,我们可以用as轻松解决这个问题。我们不能把i32转成char,但我们可以把i32转成u8,然后把u8转换成char。所以在一行中,我们使用 as 将 my_number 变为 u8,再将其变为 char。现在可以编译了。

fn main() {
    let my_number = 100;
    println!("{}", my_number as u8 as char);
}

它打印的是d,因为那是100对应的char

然而,更简单的方法是告诉 Rust my_numberu8。下面是你的做法。

fn main() {
    let my_number: u8 = 100; //  change my_number to my_number: u8
    println!("{}", my_number as char);
}

所以这就是Rust中所有不同数字类型的两个原因。这里还有一个原因:usize是Rust用于索引的大小。(索引的意思是 "哪项是第一","哪项是第二"等等)usize是索引的最佳大小,因为:

  • 索引不能是负数,所以它需要是一个带u的数字
  • 它应该是大的,因为有时你需要索引很多东西,但。
  • 不可能是u64,因为32位电脑不能使用u64。

所以Rust使用了usize,这样你的计算机就可以得到它能读到的最大的数字进行索引。

我们再来了解一下char。你看到char总是一个字符,并且使用''而不是""

所有的 字符 都使用4个字节的内存,因为4个字节足以容纳任何种类的字符:

  • 基本字母和符号通常需要4个字节中的1个:a b 1 2 + - = $ @
  • 其他字母,如德语的 Umlauts 或重音,需要4个字节中的2个: ä ö ü ß è é à ñ
  • 韩文、日文或中文字符需要3或4个字节: 国 안 녕

当使用字符作为字符串的一部分时,字符串被编码以使用每个字符所需的最小内存量。

我们可以用.len()来看一下。

fn main() {
    println!("Size of a char: {}", std::mem::size_of::<char>()); // 4 bytes
    println!("Size of string containing 'a': {}", "a".len()); // .len() gives the size of the string in bytes
    println!("Size of string containing 'ß': {}", "ß".len());
    println!("Size of string containing '国': {}", "国".len());
    println!("Size of string containing '𓅱': {}", "𓅱".len());
}

这样打印出来。

Size of a char: 4
Size of string containing 'a': 1
Size of string containing 'ß': 2
Size of string containing '国': 3
Size of string containing '𓅱': 4

可以看到,a是一个字节,德文的ß是两个字节,日文的是三个字节,古埃及的𓅱是4个字节。

fn main() {
    let slice = "Hello!";
    println!("Slice is {} bytes.", slice.len());
    let slice2 = "안녕!"; // Korean for "hi"
    println!("Slice2 is {} bytes.", slice2.len());
}

这个打印:

Slice is 6 bytes.
Slice2 is 7 bytes.

slice的长度是6个字符,6个字节,但slice2的长度是3个字符,7个字节。

如果.len()给出的是以字节为单位的大小,那么以字符为单位的大小呢?这些方法我们后面会学习,但你只要记住.chars().count()就可以了。.chars().count() 将你写的东西变成字符,然后计算有多少个字符。

fn main() {
    let slice = "Hello!";
    println!("Slice is {} bytes and also {} characters.", slice.len(), slice.chars().count());
    let slice2 = "안녕!";
    println!("Slice2 is {} bytes but only {} characters.", slice2.len(), slice2.chars().count());
}

这就打印出来了。

Slice is 6 bytes and also 6 characters.
Slice2 is 7 bytes but only 3 characters.