]> git.lizzy.rs Git - rust.git/blob - src/doc/trpl/primitive-types.md
d3bf61434c9e5c75c63f649d9ffe2e2154019c49
[rust.git] / src / doc / trpl / primitive-types.md
1 % Primitive Types
2
3 The Rust language has a number of types that are considered ‘primitive’. This
4 means that they’re built-in to the language. Rust is structured in such a way
5 that the standard library also provides a number of useful types built on top
6 of these ones, as well, but these are the most primitive.
7
8 # Booleans
9
10 Rust has a built in boolean type, named `bool`. It has two values, `true` and `false`:
11
12 ```rust
13 let x = true;
14
15 let y: bool = false;
16 ```
17
18 A common use of booleans is in [`if` conditionals][if].
19
20 [if]: if.html
21
22 You can find more documentation for `bool`s [in the standard library
23 documentation][bool].
24
25 [bool]: ../std/primitive.bool.html
26
27 # `char`
28
29 The `char` type represents a single Unicode scalar value. You can create `char`s
30 with a single tick: (`'`)
31
32 ```rust
33 let x = 'x';
34 let two_hearts = '💕';
35 ```
36
37 Unlike some other languages, this means that Rust’s `char` is not a single byte,
38 but four.
39
40 You can find more documentation for `char`s [in the standard library
41 documentation][char].
42
43 [char]: ../std/primitive.char.html
44
45 # Numeric types
46
47 Rust has a variety of numeric types in a few categories: signed and unsigned,
48 fixed and variable, floating-point and integer.
49
50 These types consist of two parts: the category, and the size. For example,
51 `u16` is an unsigned type with sixteen bits of size. More bits lets you have
52 bigger numbers.
53
54 If a number literal has nothing to cause its type to be inferred, it defaults:
55
56 ```rust
57 let x = 42; // x has type i32
58
59 let y = 1.0; // y has type f64
60 ```
61
62 Here’s a list of the different numeric types, with links to their documentation
63 in the standard library:
64
65 * [i8](../std/primitive.i8.html)
66 * [i16](../std/primitive.i16.html)
67 * [i32](../std/primitive.i32.html)
68 * [i64](../std/primitive.i64.html)
69 * [u8](../std/primitive.u8.html)
70 * [u16](../std/primitive.u16.html)
71 * [u32](../std/primitive.u32.html)
72 * [u64](../std/primitive.u64.html)
73 * [isize](../std/primitive.isize.html)
74 * [usize](../std/primitive.usize.html)
75 * [f32](../std/primitive.f32.html)
76 * [f64](../std/primitive.f64.html)
77
78 Let’s go over them by category:
79
80 ## Signed and Unsigned
81
82 Integer types come in two varieties: signed and unsigned. To understand the
83 difference, let’s consider a number with four bits of size. A signed, four-bit
84 number would let you store numbers from `-8` to `+7`. Signed numbers use
85 “two’s complement representation”. An unsigned four bit number, since it does
86 not need to store negatives, can store values from `0` to `+15`.
87
88 Unsigned types use a `u` for their category, and signed types use `i`. The `i`
89 is for ‘integer’. So `u8` is an eight-bit unsigned number, and `i8` is an
90 eight-bit signed number.
91
92 ## Fixed size types
93
94 Fixed size types have a specific number of bits in their representation. Valid
95 bit sizes are `8`, `16`, `32`, and `64`. So, `u32` is an unsigned, 32-bit integer,
96 and `i64` is a signed, 64-bit integer.
97
98 ## Variable sized types
99
100 Rust also provides types whose size depends on the size of a pointer of the
101 underlying machine. These types have ‘size’ as the category, and come in signed
102 and unsigned varieties. This makes for two types: `isize` and `usize`.
103
104 ## Floating-point types
105
106 Rust also has two floating point types: `f32` and `f64`. These correspond to
107 IEEE-754 single and double precision numbers.
108
109 # Arrays
110
111 Like many programming languages, Rust has list types to represent a sequence of
112 things. The most basic is the *array*, a fixed-size list of elements of the
113 same type. By default, arrays are immutable.
114
115 ```rust
116 let a = [1, 2, 3]; // a: [i32; 3]
117 let mut m = [1, 2, 3]; // m: [i32; 3]
118 ```
119
120 Arrays have type `[T; N]`. We’ll talk about this `T` notation [in the generics
121 section][generics]. The `N` is a compile-time constant, for the length of the
122 array.
123
124 There’s a shorthand for initializing each element of an array to the same
125 value. In this example, each element of `a` will be initialized to `0`:
126
127 ```rust
128 let a = [0; 20]; // a: [i32; 20]
129 ```
130
131 You can get the number of elements in an array `a` with `a.len()`:
132
133 ```rust
134 let a = [1, 2, 3];
135
136 println!("a has {} elements", a.len());
137 ```
138
139 You can access a particular element of an array with *subscript notation*:
140
141 ```rust
142 let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3]
143
144 println!("The second name is: {}", names[1]);
145 ```
146
147 Subscripts start at zero, like in most programming languages, so the first name
148 is `names[0]` and the second name is `names[1]`. The above example prints
149 `The second name is: Brian`. If you try to use a subscript that is not in the
150 array, you will get an error: array access is bounds-checked at run-time. Such
151 errant access is the source of many bugs in other systems programming
152 languages.
153
154 You can find more documentation for `array`s [in the standard library
155 documentation][array].
156
157 [array]: ../std/primitive.array.html
158
159 # Slices
160
161 A ‘slice’ is a reference to (or “view” into) another data structure. They are
162 useful for allowing safe, efficient access to a portion of an array without
163 copying. For example, you might want to reference just one line of a file read
164 into memory. By nature, a slice is not created directly, but from an existing
165 variable. Slices have a length, can be mutable or not, and in many ways behave
166 like arrays:
167
168 ```rust
169 let a = [0, 1, 2, 3, 4];
170 let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
171 let complete = &a[..]; // A slice containing all of the elements in a
172 ```
173
174 Slices have type `&[T]`. We’ll talk about that `T` when we cover
175 [generics][generics].
176
177 [generics]: generics.html
178
179 You can find more documentation for slices [in the standard library
180 documentation][slice].
181
182 [slice]: ../std/primitive.slice.html
183
184 # `str`
185
186 Rust’s `str` type is the most primitive string type. As an [unsized type][dst],
187 it’s not very useful by itself, but becomes useful when placed behind a reference,
188 like [`&str`][strings]. As such, we’ll just leave it at that.
189
190 [dst]: unsized-types.html
191 [strings]: strings.html
192
193 You can find more documentation for `str` [in the standard library
194 documentation][str].
195
196 [str]: ../std/primitive.str.html
197
198 # Tuples
199
200 A tuple is an ordered list of fixed size. Like this:
201
202 ```rust
203 let x = (1, "hello");
204 ```
205
206 The parentheses and commas form this two-length tuple. Here’s the same code, but
207 with the type annotated:
208
209 ```rust
210 let x: (i32, &str) = (1, "hello");
211 ```
212
213 As you can see, the type of a tuple looks just like the tuple, but with each
214 position having a type name rather than the value. Careful readers will also
215 note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple.
216 In systems programming languages, strings are a bit more complex than in other
217 languages. For now, just read `&str` as a *string slice*, and we’ll learn more
218 soon.
219
220 You can assign one tuple into another, if they have the same contained types
221 and [arity]. Tuples have the same arity when they have the same length.
222
223 [arity]: glossary.html#arity
224
225 ```rust
226 let mut x = (1, 2); // x: (i32, i32)
227 let y = (2, 3); // y: (i32, i32)
228
229 x = y;
230 ```
231
232 You can access the fields in a tuple through a *destructuring let*. Here’s
233 an example:
234
235 ```rust
236 let (x, y, z) = (1, 2, 3);
237
238 println!("x is {}", x);
239 ```
240
241 Remember [before][let] when I said the left-hand side of a `let` statement was more
242 powerful than just assigning a binding? Here we are. We can put a pattern on
243 the left-hand side of the `let`, and if it matches up to the right-hand side,
244 we can assign multiple bindings at once. In this case, `let` “destructures”
245 or “breaks up” the tuple, and assigns the bits to three bindings.
246
247 [let]: variable-bindings.html
248
249 This pattern is very powerful, and we’ll see it repeated more later.
250
251 You can disambiguate a single-element tuple from a value in parentheses with a
252 comma:
253
254 ```
255 (0,); // single-element tuple
256 (0); // zero in parentheses
257 ```
258
259 ## Tuple Indexing
260
261 You can also access fields of a tuple with indexing syntax:
262
263
264 ```rust
265 let tuple = (1, 2, 3);
266
267 let x = tuple.0;
268 let y = tuple.1;
269 let z = tuple.2;
270
271 println!("x is {}", x);
272 ```
273
274 Like array indexing, it starts at zero, but unlike array indexing, it uses a
275 `.`, rather than `[]`s.
276
277 You can find more documentation for tuples [in the standard library
278 documentation][tuple].
279
280 [tuple]: ../std/primitive.tuple.html
281
282 # Functions
283
284 Functions also have a type! They look like this:
285
286 ```
287 fn foo(x: i32) -> i32 { x }
288
289 let x: fn(i32) -> i32 = foo;
290 ```
291
292 In this case, `x` is a ‘function pointer’ to a function that takes an `i32` and
293 returns an `i32`.