# 原生类型
> [primitive-types.md](https://github.com/rust-lang/rust/blob/master/src/doc/book/primitive-types.md)
commit 6ba952020fbc91bad64be1ea0650bfba52e6aab4
Rust有一系列被认为是“原生”的类型。这意味着它们是内建在语言中的。Rust被构建为在标准库中也提供了一些建立在这些类型之上的有用的类型,不过它们也大部分是原生的。
### 布尔型
Rust 有一个内建的布尔类型,叫做`bool`。它有两个值,`true`和`false`:
~~~
let x = true;
let y: bool = false;
~~~
布尔型通常用在[if语句](#)中。
你可以在[标准库文档](http://doc.rust-lang.org/nightly/std/primitive.bool.html)中找到更多关于`bool`的文档。
### `char`
`char`类型代表一个单独的 Unicode 字符的值。你可以用单引号(`'`)创建`char`:
~~~
let x = 'x';
let two_hearts = '?';
~~~
不像其它语言,这意味着Rust的`char`并不是 1 个字节,而是 4 个。
你可以在[标准库文档](http://doc.rust-lang.org/nightly/std/primitive.char.html)中找到更多关于`char`的文档。
### 数字类型
Rust有一些分类的大量数字类型:有符号和无符号,定长和变长,浮点和整型。
这些类型包含两部分:分类,和大小。例如,`u16`是一个拥有16位大小的无符号类型。更多字节让你拥有更大的数字。
如果一个数字常量没有推断它类型的条件,它采用默认类型:
~~~
let x = 42; // x has type i32
let y = 1.0; // y has type f64
~~~
这里有一个不同数字类型的列表,以及它们在标注库中的文档:
- [i8](http://doc.rust-lang.org/nightly/std/primitive.i8.html)
- [i16](http://doc.rust-lang.org/nightly/std/primitive.i16.html)
- [i32](http://doc.rust-lang.org/nightly/std/primitive.i32.html)
- [i64](http://doc.rust-lang.org/nightly/std/primitive.i64.html)
- [u8](http://doc.rust-lang.org/nightly/std/primitive.u8.html)
- [u16](http://doc.rust-lang.org/nightly/std/primitive.u16.html)
- [u32](http://doc.rust-lang.org/nightly/std/primitive.u32.html)
- [u64](http://doc.rust-lang.org/nightly/std/primitive.u64.html)
- [isize](http://doc.rust-lang.org/nightly/std/primitive.isize.html)
- [usize](http://doc.rust-lang.org/nightly/std/primitive.usize.html)
- [f32](http://doc.rust-lang.org/nightly/std/primitive.f32.html)
- [f64](http://doc.rust-lang.org/nightly/std/primitive.f64.html)
让我们按分类重温一遍:
### 有符号和无符号
整型有两种变体:有符号和无符号。为了理解它们的区别,让我们考虑一个 4 比特大小的数字。一个有符号,4 比特数字你可以储存`-8`到`+7`的数字。有符号数采用“补码”表示。一个无符号 4 比特的数字,因为它不需要储存负数,可以出储存`0`到`+15`的数字。
### 固定大小类型
固定大小类型在其表现中有特定数量的位。有效的位大小是`8`,`16`,`32`和`64`。那么,`u32`是无符号的,32 位整型,而`i64`是有符号,64 位整型。
### 可变大小类型
Rust 也提供了依赖底层机器指针大小的类型。这些类型拥有“size”分类,并有有符号和无符号变体。它有两个类型:`isize`和`usize`。
### 浮点类型
Rust 也有两个浮点类型:`f32`和`f64`。它们对应 IEEE-754 单精度和双精度浮点数。
### 数组
像很多编程语言一样,Rust有用来表示数据序列的列表类型。最基本的是*数组*,一个定长相同类型的元素列表。数组默认是不可变的。
~~~
let a = [1, 2, 3]; // a: [i32; 3]
let mut m = [1, 2, 3]; // m: [i32; 3]
~~~
数组的类型是`[T; N]`。我们会在[泛型部分](#)的时候讨论这个`T`标记。`N`是一个编译时常量,代表数组的长度。
有一个可以将数组中每一个元素初始化为相同值的简写。在这个例子中,`a`的每个元素都被初始化为`0`:
~~~
let a = [0; 20]; // a: [i32; 20]
~~~
你可以用`a.len()`来获取数组`a`的元素数量:
~~~
let a = [1, 2, 3];
println!("a has {} elements", a.len());
~~~
你可以用*下标*(*subscript notation*)来访问特定的元素:
~~~
let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3]
println!("The second name is: {}", names[1]);
~~~
就跟大部分编程语言一个样,下标从0开始,所以第一个元素是`names[0]`,第二个是`names[1]`。上面的例子会打印出`The second name is: Brian`。如果你尝试使用一个不在数组中的下标,你会得到一个错误:数组访问会在运行时进行边界检查。这种不适当的访问时其它系统编程语言中很多bug的根源。
你可以在[标准库文档](http://doc.rust-lang.org/stable/std/primitive.array.html)中找到更多关于`array`的文档。
### 切片(Slices)
一个*切片*(*slice*)是一个数组的引用(或者“视图”)。它有利于安全,有效的访问数组的一部分而不用进行拷贝。比如,你可能只想要引用读入到内存的文件中的一行。原理上,片段并不是直接创建的,而是引用一个已经存在的变量。片段有预定义的长度,可以是可变也可以是不可变的。
### 切片语法
你可以用一个`&`和`[]`的组合从多种数据类型创建一个切片。`&`表明切片类似于[引用](#),这个我们会在本部分的后面详细介绍。带有一个范围的`[]`,允许你定义切片的长度:
~~~
let a = [0, 1, 2, 3, 4];
let complete = &a[..]; // A slice containing all of the elements in a
let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
~~~
片段拥有`&[T]`类型。当我们涉及到[泛型](#)时会讨论这个`T`。
你可以在[标准库文档](http://doc.rust-lang.org/stable/std/primitive.slice.html)中找到更多关于`slices`的文档。
### `str`
Rust的`str`类型是最原始的字符串类型。作为一个[不定长类型](#),它本身并不是非常有用,不过当它用在引用后是就有用了,例如[&str](#)。如你所见,我们到时候再讲。
你可以在[标准库文档](http://doc.rust-lang.org/stable/std/primitive.str.html)中找到更多关于`str`的文档。
### 元组(Tuples)
元组(tuples)是固定大小的有序列表。如下:
~~~
let x = (1, "hello");
~~~
这是一个长度为2的元组,有括号和逗号组成。下面也是同样的元组,不过注明了数据类型:
~~~
let x: (i32, &str) = (1, "hello");
~~~
如你所见,元组的类型跟元组看起来很像,只不过类型取代的值的位置。细心的读者可能会注意到元组是异质的:这个元组中有一个`i32`和一个`&str`。在系统编程语言中,字符串要比其它语言中来的复杂。现在,可以认为`&str`是一个*字符串片段*(*string slice*),我们马上会讲到它。
你可以把一个元组赋值给另一个,如果它们包含相同的类型和[数量](#)。当元组有相同的长度时它们有相同的数量。
~~~
let mut x = (1, 2); // x: (i32, i32)
let y = (2, 3); // y: (i32, i32)
x = y;
~~~
你可以通过一个*解构let*(*destructuring let*)访问元组中的字段。下面是一个例子:
~~~
let (x, y, z) = (1, 2, 3);
println!("x is {}", x);
~~~
还记得[之前](#)我曾经说过`let`语句的左侧远比一个赋值绑定强大吗?这就是证据。我们可以在`let`左侧写一个模式,如果它能匹配右侧的话,我们可以一次写多个绑定。这种情况下,`let`“解构”或“拆开”了元组,并分成了三个绑定。
这个模式是很强大的,我们后面会经常看到它。
你可以一个逗号来消除一个单元素元组和一个括号中的值的歧义:
~~~
(0,); // single-element tuple
(0); // zero in parentheses
~~~
### 元组索引(Tuple Indexing)
你也可以用索引语法访问一个元组的字段:
~~~
let tuple = (1, 2, 3);
let x = tuple.0;
let y = tuple.1;
let z = tuple.2;
println!("x is {}", x);
~~~
就像数组索引,它从`0`开始,不过也不像数组索引,它使用`.`,而不是`[]`。
你可以在[标准库文档](http://doc.rust-lang.org/stable/std/primitive.tuple.html)中找到更多关于`tuple`的文档。
### 函数
函数也有一个类型!它们看起来像这样:
~~~
fn foo(x: i32) -> i32 { x }
let x: fn(i32) -> i32 = foo;
~~~
在这个例子中,`x`是一个“函数指针”,指向一个获取一个`i32`参数并返回一个`i32`值的函数。
- 前言
- 贡献者
- 1.介绍
- 2.准备
- 3.学习 Rust
- 3.1.猜猜看
- 3.2.哲学家就餐问题
- 3.3.其它语言中的 Rust
- 4.语法和语义
- 4.1.变量绑定
- 4.2.函数
- 4.3.原生类型
- 4.4.注释
- 4.5.If语句
- 4.6.循环
- 4.7.所有权
- 4.8.引用和借用
- 4.9.生命周期
- 4.10.可变性
- 4.11.结构体
- 4.12.枚举
- 4.13.匹配
- 4.14.模式
- 4.15.方法语法
- 4.16.Vectors
- 4.17.字符串
- 4.18.泛型
- 4.19.Traits
- 4.20.Drop
- 4.21.if let
- 4.22.trait 对象
- 4.23.闭包
- 4.24.通用函数调用语法
- 4.25.crate 和模块
- 4.26.const和static
- 4.27.属性
- 4.28.type别名
- 4.29.类型转换
- 4.30.关联类型
- 4.31.不定长类型
- 4.32.运算符和重载
- 4.33.Deref强制多态
- 4.34.宏
- 4.35.裸指针
- 4.36.不安全代码
- 5.高效 Rust
- 5.1.栈和堆
- 5.2.测试
- 5.3.条件编译
- 5.4.文档
- 5.5.迭代器
- 5.6.并发
- 5.7.错误处理
- 5.8.选择你的保证
- 5.9.外部函数接口
- 5.10.Borrow 和 AsRef
- 5.11.发布途径
- 5.12.不使用标准库
- 6.Rust 开发版
- 6.1.编译器插件
- 6.2.内联汇编
- 6.4.固有功能
- 6.5.语言项
- 6.6.链接进阶
- 6.7.基准测试
- 6.8.装箱语法和模式
- 6.9.切片模式
- 6.10.关联常量
- 6.11.自定义内存分配器
- 7.词汇表
- 8.语法索引
- 9.参考文献
- 附录:名词中英文对照