]> git.proxmox.com Git - rustc.git/blame - src/doc/book/src/ch03-02-data-types.md
New upstream version 1.55.0+dfsg1
[rustc.git] / src / doc / book / src / ch03-02-data-types.md
CommitLineData
13cf67c4
XL
1## Data Types
2
3Every value in Rust is of a certain *data type*, which tells Rust what kind of
4data is being specified so it knows how to work with that data. We’ll look at
5two data type subsets: scalar and compound.
6
7Keep in mind that Rust is a *statically typed* language, which means that it
8must know the types of all variables at compile time. The compiler can usually
9infer what type we want to use based on the value and how we use it. In cases
10when many types are possible, such as when we converted a `String` to a numeric
dc9dc135
XL
11type using `parse` in the [“Comparing the Guess to the Secret
12Number”][comparing-the-guess-to-the-secret-number]<!-- ignore --> section in
13Chapter 2, we must add a type annotation, like this:
13cf67c4
XL
14
15```rust
16let guess: u32 = "42".parse().expect("Not a number!");
17```
18
19If we don’t add the type annotation here, Rust will display the following
20error, which means the compiler needs more information from us to know which
21type we want to use:
22
f035d41b 23```console
74b04a01 24{{#include ../listings/ch03-common-programming-concepts/output-only-01-no-type-annotations/output.txt}}
13cf67c4
XL
25```
26
27You’ll see different type annotations for other data types.
28
29### Scalar Types
30
31A *scalar* type represents a single value. Rust has four primary scalar types:
32integers, floating-point numbers, Booleans, and characters. You may recognize
33these from other programming languages. Let’s jump into how they work in Rust.
34
35#### Integer Types
36
37An *integer* is a number without a fractional component. We used one integer
38type in Chapter 2, the `u32` type. This type declaration indicates that the
39value it’s associated with should be an unsigned integer (signed integer types
40start with `i`, instead of `u`) that takes up 32 bits of space. Table 3-1 shows
41the built-in integer types in Rust. Each variant in the Signed and Unsigned
42columns (for example, `i16`) can be used to declare the type of an integer
43value.
44
45<span class="caption">Table 3-1: Integer Types in Rust</span>
46
47| Length | Signed | Unsigned |
48|---------|---------|----------|
49| 8-bit | `i8` | `u8` |
50| 16-bit | `i16` | `u16` |
51| 32-bit | `i32` | `u32` |
52| 64-bit | `i64` | `u64` |
53| 128-bit | `i128` | `u128` |
54| arch | `isize` | `usize` |
55
56Each variant can be either signed or unsigned and has an explicit size.
57*Signed* and *unsigned* refer to whether it’s possible for the number to be
3dfed10e 58negative—in other words, whether the number needs to have a sign
13cf67c4
XL
59with it (signed) or whether it will only ever be positive and can therefore be
60represented without a sign (unsigned). It’s like writing numbers on paper: when
61the sign matters, a number is shown with a plus sign or a minus sign; however,
62when it’s safe to assume the number is positive, it’s shown with no sign.
9fa01778 63Signed numbers are stored using [two’s complement](https://en.wikipedia.org/wiki/Two%27s_complement) representation.
13cf67c4
XL
64
65Each signed variant can store numbers from -(2<sup>n - 1</sup>) to 2<sup>n -
661</sup> - 1 inclusive, where *n* is the number of bits that variant uses. So an
67`i8` can store numbers from -(2<sup>7</sup>) to 2<sup>7</sup> - 1, which equals
68-128 to 127. Unsigned variants can store numbers from 0 to 2<sup>n</sup> - 1,
69so a `u8` can store numbers from 0 to 2<sup>8</sup> - 1, which equals 0 to 255.
70
71Additionally, the `isize` and `usize` types depend on the kind of computer your
72program is running on: 64 bits if you’re on a 64-bit architecture and 32 bits
73if you’re on a 32-bit architecture.
74
75You can write integer literals in any of the forms shown in Table 3-2. Note
136023e0
XL
76that number literals that can be multiple numeric types allow a type suffix,
77such as `57u8`, to designate the type. Number literals can also use `_` as a
78visual separator to make the number easier to read, such as `1_000`, which will
79have the same value as if you had specified `1000`.
13cf67c4
XL
80
81<span class="caption">Table 3-2: Integer Literals in Rust</span>
82
83| Number literals | Example |
84|------------------|---------------|
85| Decimal | `98_222` |
86| Hex | `0xff` |
87| Octal | `0o77` |
88| Binary | `0b1111_0000` |
89| Byte (`u8` only) | `b'A'` |
90
91So how do you know which type of integer to use? If you’re unsure, Rust’s
136023e0
XL
92defaults are generally good places to start: integer types default to `i32`.
93The primary situation in which you’d use `isize` or `usize` is when indexing
94some sort of collection.
13cf67c4 95
9fa01778
XL
96> ##### Integer Overflow
97>
532ac7d7
XL
98> Let’s say you have a variable of type `u8` that can hold values between 0 and 255.
99> If you try to change the variable to a value outside of that range, such
100> as 256, *integer overflow* will occur. Rust has some interesting rules
101> involving this behavior. When you’re compiling in debug mode, Rust includes
102> checks for integer overflow that cause your program to *panic* at runtime if
103> this behavior occurs. Rust uses the term panicking when a program exits with
104> an error; we’ll discuss panics in more depth in the [“Unrecoverable Errors
dc9dc135
XL
105> with `panic!`”][unrecoverable-errors-with-panic]<!-- ignore --> section in
106> Chapter 9.
9fa01778 107>
532ac7d7
XL
108> When you’re compiling in release mode with the `--release` flag, Rust does
109> *not* include checks for integer overflow that cause panics. Instead, if
110> overflow occurs, Rust performs *two’s complement wrapping*. In short, values
111> greater than the maximum value the type can hold “wrap around” to the minimum
112> of the values the type can hold. In the case of a `u8`, 256 becomes 0, 257
113> becomes 1, and so on. The program won’t panic, but the variable will have a
114> value that probably isn’t what you were expecting it to have. Relying on
fc512014
XL
115> integer overflow’s wrapping behavior is considered an error.
116>
117> To explicitly handle the possibility of overflow, you can use these families
118> of methods that the standard library provides on primitive numeric types:
119>
120> - Wrap in all modes with the `wrapping_*` methods, such as `wrapping_add`
121> - Return the `None` value if there is overflow with the `checked_*` methods
122> - Return the value and a boolean indicating whether there was overflow with
123> the `overflowing_*` methods
124> - Saturate at the value's minimum or maximum values with `saturating_*`
125> methods
13cf67c4
XL
126
127#### Floating-Point Types
128
129Rust also has two primitive types for *floating-point numbers*, which are
130numbers with decimal points. Rust’s floating-point types are `f32` and `f64`,
131which are 32 bits and 64 bits in size, respectively. The default type is `f64`
132because on modern CPUs it’s roughly the same speed as `f32` but is capable of
133more precision.
134
135Here’s an example that shows floating-point numbers in action:
136
137<span class="filename">Filename: src/main.rs</span>
138
139```rust
74b04a01 140{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-06-floating-point/src/main.rs}}
13cf67c4
XL
141```
142
143Floating-point numbers are represented according to the IEEE-754 standard. The
144`f32` type is a single-precision float, and `f64` has double precision.
145
146#### Numeric Operations
147
148Rust supports the basic mathematical operations you’d expect for all of the
149number types: addition, subtraction, multiplication, division, and remainder.
150The following code shows how you’d use each one in a `let` statement:
151
152<span class="filename">Filename: src/main.rs</span>
153
154```rust
74b04a01 155{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-07-numeric-operations/src/main.rs}}
13cf67c4
XL
156```
157
158Each expression in these statements uses a mathematical operator and evaluates
29967ef6 159to a single value, which is then bound to a variable. [Appendix B][appendix_b]<!-- ignore --> contains a
13cf67c4
XL
160list of all operators that Rust provides.
161
162#### The Boolean Type
163
164As in most other programming languages, a Boolean type in Rust has two possible
9fa01778
XL
165values: `true` and `false`. Booleans are one byte in size. The Boolean type in
166Rust is specified using `bool`. For example:
13cf67c4
XL
167
168<span class="filename">Filename: src/main.rs</span>
169
170```rust
74b04a01 171{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-08-boolean/src/main.rs}}
13cf67c4
XL
172```
173
69743fb6 174The main way to use Boolean values is through conditionals, such as an `if`
9fa01778
XL
175expression. We’ll cover how `if` expressions work in Rust in the [“Control
176Flow”][control-flow]<!-- ignore --> section.
13cf67c4
XL
177
178#### The Character Type
179
180So far we’ve worked only with numbers, but Rust supports letters too. Rust’s
181`char` type is the language’s most primitive alphabetic type, and the following
9fa01778 182code shows one way to use it. (Note that `char` literals are specified with
13cf67c4
XL
183single quotes, as opposed to string literals, which use double quotes.)
184
185<span class="filename">Filename: src/main.rs</span>
186
187```rust
74b04a01 188{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-09-char/src/main.rs}}
13cf67c4
XL
189```
190
9fa01778
XL
191Rust’s `char` type is four bytes in size and represents a Unicode Scalar Value,
192which means it can represent a lot more than just ASCII. Accented letters;
193Chinese, Japanese, and Korean characters; emoji; and zero-width spaces are all
194valid `char` values in Rust. Unicode Scalar Values range from `U+0000` to
195`U+D7FF` and `U+E000` to `U+10FFFF` inclusive. However, a “character” isn’t
196really a concept in Unicode, so your human intuition for what a “character” is
197may not match up with what a `char` is in Rust. We’ll discuss this topic in
198detail in [“Storing UTF-8 Encoded Text with Strings”][strings]<!-- ignore -->
199in Chapter 8.
13cf67c4
XL
200
201### Compound Types
202
203*Compound types* can group multiple values into one type. Rust has two
204primitive compound types: tuples and arrays.
205
206#### The Tuple Type
207
e74abb32
XL
208A tuple is a general way of grouping together a number of values with a variety
209of types into one compound type. Tuples have a fixed length: once declared,
210they cannot grow or shrink in size.
13cf67c4
XL
211
212We create a tuple by writing a comma-separated list of values inside
213parentheses. Each position in the tuple has a type, and the types of the
214different values in the tuple don’t have to be the same. We’ve added optional
215type annotations in this example:
216
217<span class="filename">Filename: src/main.rs</span>
218
219```rust
74b04a01 220{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-10-tuples/src/main.rs}}
13cf67c4
XL
221```
222
223The variable `tup` binds to the entire tuple, because a tuple is considered a
224single compound element. To get the individual values out of a tuple, we can
225use pattern matching to destructure a tuple value, like this:
226
227<span class="filename">Filename: src/main.rs</span>
228
229```rust
74b04a01 230{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-11-destructuring-tuples/src/main.rs}}
13cf67c4
XL
231```
232
233This program first creates a tuple and binds it to the variable `tup`. It then
234uses a pattern with `let` to take `tup` and turn it into three separate
235variables, `x`, `y`, and `z`. This is called *destructuring*, because it breaks
236the single tuple into three parts. Finally, the program prints the value of
237`y`, which is `6.4`.
238
239In addition to destructuring through pattern matching, we can access a tuple
240element directly by using a period (`.`) followed by the index of the value we
241want to access. For example:
242
243<span class="filename">Filename: src/main.rs</span>
244
245```rust
74b04a01 246{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-12-tuple-indexing/src/main.rs}}
13cf67c4
XL
247```
248
249This program creates a tuple, `x`, and then makes new variables for each
e74abb32
XL
250element by using their respective indices. As with most programming languages,
251the first index in a tuple is 0.
13cf67c4
XL
252
253#### The Array Type
254
255Another way to have a collection of multiple values is with an *array*. Unlike
256a tuple, every element of an array must have the same type. Arrays in Rust are
257different from arrays in some other languages because arrays in Rust have a
258fixed length, like tuples.
259
260In Rust, the values going into an array are written as a comma-separated list
261inside square brackets:
262
263<span class="filename">Filename: src/main.rs</span>
264
265```rust
74b04a01 266{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-13-arrays/src/main.rs}}
13cf67c4
XL
267```
268
269Arrays are useful when you want your data allocated on the stack rather than
69743fb6 270the heap (we will discuss the stack and the heap more in Chapter 4) or when
13cf67c4
XL
271you want to ensure you always have a fixed number of elements. An array isn’t
272as flexible as the vector type, though. A vector is a similar collection type
273provided by the standard library that *is* allowed to grow or shrink in size.
274If you’re unsure whether to use an array or a vector, you should probably use a
275vector. Chapter 8 discusses vectors in more detail.
276
277An example of when you might want to use an array rather than a vector is in a
278program that needs to know the names of the months of the year. It’s very
279unlikely that such a program will need to add or remove months, so you can use
e74abb32 280an array because you know it will always contain 12 elements:
13cf67c4
XL
281
282```rust
283let months = ["January", "February", "March", "April", "May", "June", "July",
284 "August", "September", "October", "November", "December"];
285```
286
532ac7d7
XL
287You would write an array’s type by using square brackets, and within the
288brackets include the type of each element, a semicolon, and then the number of
289elements in the array, like so:
13cf67c4
XL
290
291```rust
292let a: [i32; 5] = [1, 2, 3, 4, 5];
293```
294
9fa01778 295Here, `i32` is the type of each element. After the semicolon, the number `5`
e74abb32 296indicates the array contains five elements.
9fa01778 297
532ac7d7 298Writing an array’s type this way looks similar to an alternative syntax for
9fa01778 299initializing an array: if you want to create an array that contains the same
532ac7d7
XL
300value for each element, you can specify the initial value, followed by a
301semicolon, and then the length of the array in square brackets, as shown here:
9fa01778
XL
302
303```rust
304let a = [3; 5];
305```
306
532ac7d7 307The array named `a` will contain `5` elements that will all be set to the value
9fa01778
XL
308`3` initially. This is the same as writing `let a = [3, 3, 3, 3, 3];` but in a
309more concise way.
13cf67c4
XL
310
311##### Accessing Array Elements
312
313An array is a single chunk of memory allocated on the stack. You can access
314elements of an array using indexing, like this:
315
316<span class="filename">Filename: src/main.rs</span>
317
318```rust
74b04a01 319{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-14-array-indexing/src/main.rs}}
13cf67c4
XL
320```
321
322In this example, the variable named `first` will get the value `1`, because
323that is the value at index `[0]` in the array. The variable named `second` will
324get the value `2` from index `[1]` in the array.
325
326##### Invalid Array Element Access
327
328What happens if you try to access an element of an array that is past the end
5869c6ff
XL
329of the array? Say you change the example to the following, which uses code
330similar to the guessing game in Chapter 2 to get an array index from the user:
13cf67c4
XL
331
332<span class="filename">Filename: src/main.rs</span>
333
6a06907d 334```rust,ignore,panics
74b04a01 335{{#rustdoc_include ../listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access/src/main.rs}}
13cf67c4
XL
336```
337
5869c6ff
XL
338This code compiles successfully. If you run this code using `cargo run` and
339enter 0, 1, 2, 3, or 4, the program will print out the corresponding value at
340that index in the array. If you instead enter a number past the end of the
341array, such as 10, you'll see output like this:
342
343<!-- manual-regeneration
344cd listings/ch03-common-programming-concepts/no-listing-15-invalid-array-access
345cargo run
34610
347-->
13cf67c4 348
f035d41b 349```console
5869c6ff
XL
350thread 'main' panicked at 'index out of bounds: the len is 5 but the index is 10', src/main.rs:19:19
351note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
13cf67c4
XL
352```
353
5869c6ff 354The program resulted in a *runtime* error at the point of using an invalid
6a06907d
XL
355value in the indexing operation. The program exited with an error message and
356didn't execute the final `println!` statement. When you attempt to access an
13cf67c4 357element using indexing, Rust will check that the index you’ve specified is less
6a06907d
XL
358than the array length. If the index is greater than or equal to the length,
359Rust will panic. This check has to happen at runtime, especially in this case,
360because the compiler can't possibly know what value a user will enter when they
361run the code later.
13cf67c4
XL
362
363This is the first example of Rust’s safety principles in action. In many
364low-level languages, this kind of check is not done, and when you provide an
365incorrect index, invalid memory can be accessed. Rust protects you against this
366kind of error by immediately exiting instead of allowing the memory access and
367continuing. Chapter 9 discusses more of Rust’s error handling.
9fa01778
XL
368
369[comparing-the-guess-to-the-secret-number]:
370ch02-00-guessing-game-tutorial.html#comparing-the-guess-to-the-secret-number
371[control-flow]: ch03-05-control-flow.html#control-flow
372[strings]: ch08-02-strings.html#storing-utf-8-encoded-text-with-strings
373[unrecoverable-errors-with-panic]: ch09-01-unrecoverable-errors-with-panic.html
532ac7d7 374[wrapping]: ../std/num/struct.Wrapping.html
29967ef6 375[appendix_b]: appendix-02-operators.md