You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
trpl-zh-cn/docs/ch03-02-data-types.html

294 lines
27 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据类型 - Rust 程序设计语言 简体中文版</title>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="Rust 程序设计语言 简体中文版">
<meta name="viewport" content="width=device-width, initial-scale=1">
<base href="">
<link rel="stylesheet" href="book.css">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
<link rel="shortcut icon" href="favicon.png">
<!-- Font Awesome -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<!-- MathJax -->
<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<!-- Fetch JQuery from CDN but have a local fallback -->
<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script>
if (typeof jQuery == 'undefined') {
document.write(unescape("%3Cscript src='jquery.js'%3E%3C/script%3E"));
}
</script>
</head>
<body class="light">
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme = localStorage.getItem('theme');
if (theme == null) { theme = 'light'; }
$('body').removeClass().addClass(theme);
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var sidebar = localStorage.getItem('sidebar');
if (sidebar === "hidden") { $("html").addClass("sidebar-hidden") }
else if (sidebar === "visible") { $("html").addClass("sidebar-visible") }
</script>
<div id="sidebar" class="sidebar">
<ul class="chapter"><li><a href="ch01-00-introduction.html"><strong>1.</strong> 介绍</a></li><li><ul class="section"><li><a href="ch01-01-installation.html"><strong>1.1.</strong> 安装</a></li><li><a href="ch01-02-hello-world.html"><strong>1.2.</strong> Hello, World!</a></li></ul></li><li><a href="ch02-00-guessing-game-tutorial.html"><strong>2.</strong> 猜猜看教程</a></li><li><a href="ch03-00-common-programming-concepts.html"><strong>3.</strong> 通用编程概念</a></li><li><ul class="section"><li><a href="ch03-01-variables-and-mutability.html"><strong>3.1.</strong> 变量和可变性</a></li><li><a href="ch03-02-data-types.html" class="active"><strong>3.2.</strong> 数据类型</a></li><li><a href="ch03-03-how-functions-work.html"><strong>3.3.</strong> 函数如何工作</a></li><li><a href="ch03-04-comments.html"><strong>3.4.</strong> 注释</a></li><li><a href="ch03-05-control-flow.html"><strong>3.5.</strong> 控制流</a></li></ul></li><li><a href="ch04-00-understanding-ownership.html"><strong>4.</strong> 认识所有权</a></li><li><ul class="section"><li><a href="ch04-01-what-is-ownership.html"><strong>4.1.</strong> 什么是所有权</a></li><li><a href="ch04-02-references-and-borrowing.html"><strong>4.2.</strong> 引用 &amp; 借用</a></li><li><a href="ch04-03-slices.html"><strong>4.3.</strong> Slices</a></li></ul></li><li><a href="ch05-00-structs.html"><strong>5.</strong> 结构体</a></li><li><ul class="section"><li><a href="ch05-01-method-syntax.html"><strong>5.1.</strong> 方法语法</a></li></ul></li><li><a href="ch06-00-enums.html"><strong>6.</strong> 枚举和模式匹配</a></li><li><ul class="section"><li><a href="ch06-01-defining-an-enum.html"><strong>6.1.</strong> 定义枚举</a></li><li><a href="ch06-02-match.html"><strong>6.2.</strong> <code>match</code>控制流运算符</a></li><li><a href="ch06-03-if-let.html"><strong>6.3.</strong> <code>if let</code>简单控制流</a></li></ul></li><li><a href="ch07-00-modules.html"><strong>7.</strong> 模块</a></li><li><ul class="section"><li><a href="ch07-01-mod-and-the-filesystem.html"><strong>7.1.</strong> <code>mod</code>和文件系统</a></li><li><a href="ch07-02-controlling-visibility-with-pub.html"><strong>7.2.</strong> 使用<code>pub</code>控制可见性</a></li><li><a href="ch07-03-importing-names-with-use.html"><strong>7.3.</strong> 使用<code>use</code>导入命名</a></li></ul></li><li><a href="ch08-00-common-collections.html"><strong>8.</strong> 通用集合类型</a></li><li><ul class="section"><li><a href="ch08-01-vectors.html"><strong>8.1.</strong> vector</a></li><li><a href="ch08-02-strings.html"><strong>8.2.</strong> 字符串</a></li><li><a href="ch08-03-hash-maps.html"><strong>8.3.</strong> 哈希 map</a></li></ul></li><li><a href="ch09-00-error-handling.html"><strong>9.</strong> 错误处理</a></li><li><ul class="section"><li><a href="ch09-01-unrecoverable-errors-with-panic.html"><strong>9.1.</strong> <code>panic!</code>与不可恢复的错误</a></li><li><a href="ch09-02-recoverable-errors-with-result.html"><strong>9.2.</strong> <code>Result</code>与可恢复的错误</a></li><li><a href="ch09-03-to-panic-or-not-to-panic.html"><strong>9.3.</strong> <code>panic!</code>还是不<code>panic!</code></a></li></ul></li><li><a href="ch10-00-generics.html"><strong>10.</strong> 泛型、trait 和生命周期</a></li><li><ul class="section"><li><a href="ch10-01-syntax.html"><strong>10.1.</strong> 泛型数据类型</a></li><li><a href="ch10-02-traits.html"><strong>10.2.</strong> trait定义共享的行为</a></li><li><a href="ch10-03-lifetime-syntax.html"><strong>10.3.</strong> 生命周期与引用有效性</a></li></ul></li><li><a href="ch11-00-testing.html"><strong>11.</strong> 测试</a></li><li><ul class="section"><li><a href="ch11-01-writing-tests.html"><strong>11.1.</strong> 编写测试</a></li><li><a href="ch11-02-running-tests.html"><strong>11.2.</strong> 运行测试</a></li><li><a href="ch11-03-test-organization.html"><strong>11.3.</strong> 测试的组织结构</a></li></ul></li><li><a href="ch12-00-an-io-project.html"><strong>12.</strong> 一个 I/O 项目</a></li><li><ul class="section"><li><a href="ch12-01-accepting-command-line-arguments.html"><strong>12.1.</strong> 接受命令行参数</a></li><li><a href="ch12-02-reading-a-file.html"><strong>12.2.</strong> 读取文件</a></li><li><a href="ch12-03-improving-error-handling-and-modularity.html"><strong>12.3.</strong> 增强错误处理和模块化</a></li><li><a href="ch12-04-testing-the-librarys-functionality.html"><strong>12.4.</strong> 测试库的功能</a></li><li><a href="ch12-05-working-with-environment-variables.html"><strong>12.5.</strong> 处理环境变量</a></li><li><a href="ch12-06-writing-to-stderr-instead-of-stdout.html"><strong>12.6.</strong> 输出到<code>stderr</code>而不是<code>stdout</code></a></li></ul></li><li><a href="ch13-00-functional-features.html"><strong>13.</strong> Rust 中的函数式语言功能</a></li><li><ul class="section"><li><a href="ch13-01-closures.html"><strong>13.1.</strong> 闭包</a></li><li><a href="ch13-02-iterators.html"><strong>13.2.</strong> 迭代器</a></li><li><a href="ch13-03-improving-our-io-project.html"><strong>13.3.</strong> 改进 I/O 项目</a></li><li><a href="ch13-04-performance.html"><strong>13.4.</strong> 性能</a></li></ul></li><li><a href="ch14-00-more-about-cargo.html"><strong>14.</strong> 更多关于 Cargo 和 Crates.io</a></li><li><ul class="section"><li><a href="ch14-01-release-profiles.html"><strong>14.1.</strong> 发布配置</a></li><li><a href="ch14-02-publishing-to-crates-io.html"><strong>14.2.</strong> 将 crate 发布到 Crates.io</a></li><li><a href="ch14-03-cargo-workspaces.html"><strong>14.3.</strong> Cargo 工作空间</a></li><li><a href="ch14-04-installing-binaries.html"><strong>14.4.</strong> 使用<code>cargo install</code>从 Crates.io 安装文件</a></li><li><a href="ch14-05-extending-cargo.html"><strong>14.5.</strong> Cargo 自定义扩展命令</a></li></ul></li><li><a href="ch15-00-smart-pointers.html"><strong>15.</strong> 智能指针</a></li><li><ul class="section"><li><a href="ch15-01-box.html"><strong>15.1.</strong> <code>Box&lt;T&gt;</code>用于已知大小的堆上数据</a></li><li><a href="ch15-02-deref.html"><strong>15.2.</strong> <code>Deref</code> Trait 允许通过引用访问数据</a></li><li><a href="ch15-03-drop.html"><strong>15.3.</strong> <code>Drop</code> Trait 运行清理代码</a></li><li><a href="ch15-04-rc.html"><strong>15.4.</strong> <code>Rc&lt;T&gt;</code> 引用计数智能指针</a></li><li><a href="ch15-05-interior-mutability.html"><strong>15.5.</strong> <code>RefCell&lt;T&gt;</code>和内部可变性模式</a></li><li><a href="ch15-06-reference-cycles.html"><strong>15.6.</strong> 引用循环和内存泄漏是安全的</a></li></ul></li><li><a href="ch16-00-concurrency.html"><strong>16.</strong> 无畏并发</a></li><li><ul class="section"><li><a href="ch16-01-threads.html"><strong>16.1.</strong> 线程</a></li><li><a href="ch16-02-message-passing.html"><strong>16.2.</strong> 消息传递</a></li><li><a href="ch16-03-shared-state.html"><strong>16.3.</strong> 共享状态</a></li><li><a href="ch16-04-extensible-concurrency-sync-and-send.html"><strong>16.4.</strong> 可扩展的并发:<code>Sync</code><code>Send</code></a></li></ul></li><li><a href="ch17-00-oop.html"><strong>17.</strong> 面向对象</a></li><li><ul class="section"><li><a href="ch17-01-what-is-oo.html"><strong>17.1.</strong> 什么是面向对象?</a></li><li><a href="ch17-02-trait-objects.html"><strong>17.2.</strong> 为使用不同类型的值而设计的 trait 对象</a></li><li><a href="ch17-03-oo-design-patterns.html"><strong>17.3.</strong> 面向对象设计模式的实现</a></li></ul></li></ul>
</div>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar" class="menu-bar">
<div class="left-buttons">
<i id="sidebar-toggle" class="fa fa-bars"></i>
<i id="theme-toggle" class="fa fa-paint-brush"></i>
</div>
<h1 class="menu-title">Rust 程序设计语言 简体中文版</h1>
<div class="right-buttons">
<i id="print-button" class="fa fa-print" title="Print this book"></i>
</div>
</div>
<div id="content" class="content">
<a class="header" href="#数据类型" name="数据类型"><h2>数据类型</h2></a>
<blockquote>
<p><a href="https://github.com/rust-lang/book/blob/master/second-edition/src/ch03-02-data-types.md">ch03-02-data-types.md</a>
<br>
commit fe4833a8ef2853c55424e7747a4ef8dd64c35b32</p>
</blockquote>
<p>在 Rust 中,任何值都属于一种明确的<strong>类型</strong><em>type</em>声明它被指定了何种数据以便明确其处理方式。我们将分两部分探讨一些内建类型标量scalar和复合compound</p>
<p>Rust 是<strong>静态类型</strong><em>statically typed</em>)语言,也就是说在编译时就需要知道所有变量的类型,这一认知将贯穿整个章节,请在头脑中明确。通过值的形式及其使用方式,编译器通常可以推断出我们想要用的类型。多种类型均有可能时,比如第二章中使用 <code>parse</code><code>String</code> 转换为数字,必须增加类型注解,像这样:</p>
<pre><code class="language-rust">let guess: u32 = &quot;42&quot;.parse().expect(&quot;Not a number!&quot;);
</code></pre>
<p>如果不添加类型注解Rust 会显示如下错误。这说明编译器需要更多信息,来了解我们想要的类型:</p>
<pre><code>error[E0282]: unable to infer enough type information about `_`
--&gt; src/main.rs:2:9
|
2 | let guess = &quot;42&quot;.parse().expect(&quot;Not a number!&quot;);
| ^^^^^ cannot infer type for `_`
|
= note: type annotations or generic parameter binding required
</code></pre>
<p>在我们讨论各种数据类型时,你会看到多样的类型注解。</p>
<a class="header" href="#标量类型" name="标量类型"><h3>标量类型</h3></a>
<p><strong>标量</strong>类型代表一个单独的值。Rust 有四种基本的标量类型:整型、浮点型、布尔类型和字符类型。你可能在其他语言中见过他们,不过让我们深入了解他们在 Rust 中时如何工作的。</p>
<a class="header" href="#整型" name="整型"><h4>整型</h4></a>
<p><strong>整数</strong>是一个没有小数部分的数字。我们在这一章的前面使用过 <code>i32</code> 类型。该类型声明指示i32 关联的值应该是一个占据32比特位的有符号整数因为这个<code>i</code>,与<code>u</code>代表的无符号相对)。表格 3-1 展示了 Rust 内建的整数类型。每一种变体的有符号和无符号列(例如,<em>i32</em>)可以用来声明对应的整数值。</p>
<p><span class="caption">Table 3-1: Integer Types in Rust</span></p>
<table><thead><tr><td> Length </td><td> Signed </td><td> Unsigned </td></tr></thead>
<tr><td> 8-bit </td><td> i8 </td><td> u8 </td></tr>
<tr><td> 16-bit </td><td> i16 </td><td> u16 </td></tr>
<tr><td> 32-bit </td><td> i32 </td><td> u32 </td></tr>
<tr><td> 64-bit </td><td> i64 </td><td> u64 </td></tr>
<tr><td> arch </td><td> isize </td><td> usize </td></tr>
</table>
<p>每一种变体都可以是有符号或无符号的并有一个明确的大小。有符号和无符号代表数字能否为负值换句话说数字是否需要有一个符号有符号数或者永远为正而不需要符号无符号数。这有点像在纸上书写数字当需要考虑符号的时候数字以加号或减号作为前缀然而可以安全地假设为正数时加号前缀通常省略。有符号数以二进制补码形式twos complement representation存储如果你不清楚这是什么可以在网上搜索对其的解释超出了本书的范畴</p>
<p>每一个有符号的变体可以储存包含从 -(2<sup>n - 1</sup>) 到 2<sup>n - 1</sup> - 1 在内的数字,这里 <code>n</code> 是变体使用的位数。所以 <code>i8</code> 可以储存从 -(2<sup>7</sup>) 到 2<sup>7</sup> - 1 在内的数字,也就是从 -128 到 127。无符号的变体可以储存从 0 到 2<sup>n</sup> - 1 的数字,所以 <code>u8</code> 可以储存从 0 到 2<sup>8</sup> - 1 的数字,也就是从 0 到 255。</p>
<p>另外,<code>isize</code><code>usize</code> 类型依赖运行程序的计算机架构64 位架构上他们是 64 位的, 32 位架构上他们是 32 位的。</p>
<p>可以使用表格 3-2 中的任何一种形式编写数字字面值。除字节以外的其它字面值允许使用类型后缀,例如 <code>57u8</code>,允许使用 <code>_</code> 做为分隔符以方便读数,例如 <code>1_000</code> (分隔符的数量与位置并不影响实际的数字)。</p>
<p><span class="caption">Table 3-2: Integer Literals in Rust</span></p>
<table><thead><tr><td> Number literals </td><td> Example </td></tr></thead>
<tr><td> Decimal </td><td> <code>98_222</code> </td></tr>
<tr><td> Hex </td><td> <code>0xff</code> </td></tr>
<tr><td> Octal </td><td> <code>0o77</code> </td></tr>
<tr><td> Binary </td><td> <code>0b1111_0000</code> </td></tr>
<tr><td> Byte (<code>u8</code> only) </td><td> <code>b'A'</code> </td></tr>
</table>
<p>那么该使用哪种类型的数字呢如果拿不定主意Rust 的默认类型通常就很好,数字类型默认是 <code>i32</code>:它通常是最快的,甚至在 64 位系统上也是。<code>isize</code><code>usize</code> 的主要作为集合的索引。</p>
<a class="header" href="#浮点型" name="浮点型"><h4>浮点型</h4></a>
<p>Rust 同样有两个主要的<strong>浮点数</strong>类型,<code>f32</code><code>f64</code>,它们是带小数点的数字,分别占 32 位和 64 位比特。默认类型是 <code>f64</code>,因为它与 <code>f32</code> 速度差不多,然而精度更高。在 32 位系统上也能够使用 <code>f64</code>,不过比使用 <code>f32</code> 要慢。多数情况下,以潜在的性能损耗换取更高的精度是合理的;如果觉得浮点数的大小是个麻烦,你应该以性能测试作为决策依据。</p>
<p>这是一个展示浮点数的实例:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust">fn main() {
let x = 2.0; // f64
let y: f32 = 3.0; // f32
}
</code></pre>
<p>浮点数采用 IEEE-754 标准表示。<code>f32</code>是单精度浮点数,<code>f64</code>是双精度浮点数。</p>
<a class="header" href="#数字运算符" name="数字运算符"><h4>数字运算符</h4></a>
<p>Rust 支持所有数字类型常见的基本数学运算操作:加法、减法、乘法、除法以及余数。如下代码展示了如何使用一个<code>let</code>语句来使用他们:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust">fn main() {
// addition
let sum = 5 + 10;
// subtraction
let difference = 95.5 - 4.3;
// multiplication
let product = 4 * 30;
// division
let quotient = 56.7 / 32.2;
// remainder
let remainder = 43 % 5;
}
</code></pre>
<p>这些语句中的每个表达式使用了一个数学运算符并计算出了一个值,他们绑定到了一个变量。附录 B 包含了一个 Rust 提供的所有运算符的列表。</p>
<a class="header" href="#布尔型" name="布尔型"><h4>布尔型</h4></a>
<p>正如其他大部分编程语言一样Rust 中的布尔类型有两个可能的值:<code>true</code><code>false</code>。Rust 中的布尔类型使用<code>bool</code>表示。例如:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust">fn main() {
let t = true;
let f: bool = false; // with explicit type annotation
}
</code></pre>
<p>使用布尔值的主要场景是条件表达式,例如<code>if</code>。在“控制流”“Control Flow”部分将讲到<code>if</code>表达式在 Rust 中如何工作。</p>
<a class="header" href="#字符类型" name="字符类型"><h4>字符类型</h4></a>
<p>目前为止只使用到了数字,不过 Rust 也支持字符。Rust 的<code>char</code>类型是大部分语言中基本字母字符类型,如下代码展示了如何使用它:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust">fn main() {
let c = 'z';
let z = '';
let heart_eyed_cat = '😻';
}
</code></pre>
<p>Rust 的<code>char</code>类型代表了一个 Unicode 变量值Unicode Scalar Value这意味着它可以比 ASCII 表示更多内容。拼音字母Accented letters中文/日文/汉语等象形文字emoji絵文字以及零长度的空白字符对于 Rust <code>char</code>类型都是有效的。Unicode 标量值包含从 <code>U+0000</code><code>U+D7FF</code><code>U+E000</code><code>U+10FFFF</code> 之间的值。不过,“字符”并不是一个 Unicode 中的概念,所以人直觉上的“字符”可能与 Rust 中的<code>char</code>并不符合。第八章的“字符串”部分将详细讨论这个主题。</p>
<a class="header" href="#复合类型" name="复合类型"><h3>复合类型</h3></a>
<p><strong>复合类型</strong>可以将多个其他类型的值组合成一个类型。Rust 有两个原生的复合类型元组tuple和数组array</p>
<a class="header" href="#将值组合进元组" name="将值组合进元组"><h4>将值组合进元组</h4></a>
<p>元组是一个将多个其他类型的值组合进一个复合类型的主要方式。</p>
<p>我们使用一个括号中的逗号分隔的值列表来创建一个元组。元组中的每一个位置都有一个类型,而且这些不同值的类型也不必是相同的。这个例子中使用了额外的可选类型注解:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust">fn main() {
let tup: (i32, f64, u8) = (500, 6.4, 1);
}
</code></pre>
<p><code>tup</code>变量绑定了整个元组因为元组被认为是一个单独的复合元素。为了从元组中获取单个的值可以使用模式匹配pattern matching来解构destructure )元组,像这样:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust">fn main() {
let tup = (500, 6.4, 1);
let (x, y, z) = tup;
println!(&quot;The value of y is: {}&quot;, y);
}
</code></pre>
<p>程序首先创建了一个元组并绑定到<code>tup</code>变量上。接着使用了<code>let</code>和一个模式将<code>tup</code>分成了三个不同的变量,<code>x</code><code>y</code><code>z</code>。这叫做<em>解构</em><em>destructuring</em>),因为它将一个元组拆成了三个部分。最后,程序打印出了<code>y</code>的值,也就是<code>6.4</code></p>
<p>除了使用模式匹配解构之外,也可以使用点号(<code>.</code>)后跟值的索引来直接访问他们。例如:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust">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;
}
</code></pre>
<p>这个程序创建了一个元组,<code>x</code>,并接着使用索引为每个元素创建新变量。跟大多数编程语言一样,元组的第一个索引值是 0。</p>
<a class="header" href="#数组" name="数组"><h4>数组</h4></a>
<p>另一个获取一个多个值集合的方式是<strong>数组</strong><em>array</em>。与元组不同数组中的每个元素的类型必须相同。Rust 中的数组与一些其他语言中的数组不同,因为 Rust 中的数组是固定长度的:一旦声明,他们的长度不能增长或缩小。</p>
<p>Rust 中数组的值位于中括号中的逗号分隔的列表中:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust">fn main() {
let a = [1, 2, 3, 4, 5];
}
</code></pre>
<p>数组在想要在栈stack而不是在堆heap上为数据分配空间时十分有用第四章将讨论栈与堆的更多内容或者是想要确保总是有固定数量的元素时。虽然它并不如 vector 类型那么灵活。vector 类型是标准库提供的一个<strong>允许</strong>增长和缩小长度的类似数组的集合类型。当不确定是应该使用数组还是 vector 的时候,你可能应该使用 vector第八章会详细讨论 vector。</p>
<p>一个你可能想要使用数组而不是 vector 的例子是当程序需要知道一年中月份的名字时。程序不大可能回去增加或减少月份,这时你可以使用数组因为我们知道它总是含有 12 个元素:</p>
<pre><code class="language-rust">let months = [&quot;January&quot;, &quot;February&quot;, &quot;March&quot;, &quot;April&quot;, &quot;May&quot;, &quot;June&quot;, &quot;July&quot;,
&quot;August&quot;, &quot;September&quot;, &quot;October&quot;, &quot;November&quot;, &quot;December&quot;];
</code></pre>
<a class="header" href="#访问数组元素" name="访问数组元素"><h5>访问数组元素</h5></a>
<p>数组是一整块分配在栈上的内存。可以使用索引来访问数组的元素,像这样:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust">fn main() {
let a = [1, 2, 3, 4, 5];
let first = a[0];
let second = a[1];
}
</code></pre>
<p>在这个例子中,叫做<code>first</code>的变量的值是<code>1</code>,因为它是数组索引<code>[0]</code>的值。<code>second</code>将会是数组索引<code>[1]</code>的值<code>2</code></p>
<a class="header" href="#无效的数组元素访问" name="无效的数组元素访问"><h5>无效的数组元素访问</h5></a>
<p>如果我们访问数组结尾之后的元素会发生什么呢?比如我们将上面的例子改为如下:</p>
<p><span class="filename">Filename: src/main.rs</span></p>
<pre><code class="language-rust,ignore">fn main() {
let a = [1, 2, 3, 4, 5];
let element = a[10];
println!(&quot;The value of element is: {}&quot;, element);
}
</code></pre>
<p>使用<code>cargo run</code>运行代码后会产生如下结果:</p>
<pre><code>$ cargo run
Compiling arrays v0.1.0 (file:///projects/arrays)
Running `target/debug/arrays`
thread '&lt;main&gt;' panicked at 'index out of bounds: the len is 5 but the index is
10', src/main.rs:4
note: Run with `RUST_BACKTRACE=1` for a backtrace.
error: Process didn't exit successfully: `target/debug/arrays` (exit code: 101)
</code></pre>
<p>编译并没有产生任何错误,不过程序会导致一个<strong>运行时</strong><em>runtime</em>错误并且不会成功退出。当尝试用索引访问一个元素时Rust 会检查指定的索引是否小于数组的长度。如果索引超出了数组长度Rust 会<em>panic</em>,这是 Rust 中的术语,它用于程序因为错误而退出的情况。</p>
<p>这是第一个在实战中遇到的 Rust 安全原则的例子。在很多底层语言中并没有进行这类检查这样当提供了一个不正确的索引时就会访问无效的内存。Rust 通过立即退出而不是允许内存访问并继续执行来使你免受这类错误困扰。第九章会讨论更多 Rust 的错误处理。</p>
</div>
<!-- Mobile navigation buttons -->
<a href="ch03-01-variables-and-mutability.html" class="mobile-nav-chapters previous">
<i class="fa fa-angle-left"></i>
</a>
<a href="ch03-03-how-functions-work.html" class="mobile-nav-chapters next">
<i class="fa fa-angle-right"></i>
</a>
</div>
<a href="ch03-01-variables-and-mutability.html" class="nav-chapters previous" title="You can navigate through the chapters using the arrow keys">
<i class="fa fa-angle-left"></i>
</a>
<a href="ch03-03-how-functions-work.html" class="nav-chapters next" title="You can navigate through the chapters using the arrow keys">
<i class="fa fa-angle-right"></i>
</a>
</div>
<!-- Local fallback for Font Awesome -->
<script>
if ($(".fa").css("font-family") !== "FontAwesome") {
$('<link rel="stylesheet" type="text/css" href="_FontAwesome/css/font-awesome.css">').prependTo('head');
}
</script>
<!-- Livereload script (if served using the cli tool) -->
<script src="highlight.js"></script>
<script src="book.js"></script>
</body>
</html>