Types and Values
Computers store data in memory. Memory consists of a sequence of bytes, where each byte stores 8 bits. A byte is the smallest unit that a computer can address (read or write), and a bit is the smallest unit of data.
Bytes may represent different types of data. For example, one byte may represent an 8-bit unsigned integer, a 7-bit signed integer, or an ASCII character. A type defines a set of valid values and operations on these values. For example, the u8
type defines values in the range [0, 255] and arithmetic operations on them.
Type determines how the compiler interprets bytes in memory as values. For example, if a memory byte stores the bit pattern 10000000, the compiler interprets it as
- the integer 128 if the type is
u8
(8-bit unsigned integer). - the integer -128 if the type is
i8
(8-bit signed integer).
We can divide types into three categories:
- atomic primitive types
- composite primitive types
- custom types
Atomic primitive types
Atomic primitive types are defined by the compiler and cannot be customized by the user. The compiler implements the Copy
trait on these types.
bool
The bool
type has two values: true
and false
.
Integer types
Rust defines the following machine-independent integer types, which contain 1, 2, 4, 8 bytes, respectively.
- Signed integers:
i8
,i16
,i32
,i64
. - Unsigned integers:
u8
,u16
,u32
,u64
.
Rust also defines the following machine-dependent integer types, whose lengths are large enough to store the addresses of the machine:
isize
: signed integer.usize
: unsigned integer.
Floating point types
f32
: 32-bit floating point.f64
: 64-bit floating point.
Textual types
char
: contains a Unicode scalar value in 4 bytes. For example,
'a'
'锈'
str
: contains a Unicode string (a sequence of Unicode scalar values). This type is special: because strings of different lengths have the same typestr
, the size of this type is unknown at compile time. Therefore, programs may not use this type directly but must use it only via a pointer type, such as&str
. For example,
"Hello, world"
"你好,世界"
Composite primitive types
Composite primitive types contain other types.
Arrays and slices
- Array
[T; N]
: containsN
elements of the typeT
. For example:
// Type: [i32; 1]
[1]
// Type: [&str; 2]
["Hello", "World"]
A program can access an element of an array using the expression [i]
(the index i
starts from 0), e.g.:
assert_eq!(["Hello", "World"][1], "World");
assert_eq!(x, y)
is a macro. It panics if x
and y
are different, and does nothing otherwise.
- Slice
&[T]
: contains a pointer to a range of elements in an array whose elements have the typeT
. You may create a slice from an array or another slice. For example:
// A slice containing the elements (start, start + 1, ..., end - 1) in `array`
&array[start..end]
// Same as `&array[0..end]`
&array[..end]
// Same as `&array[start..array.len()]`
&array[start..]
// Same as &array[0..array.len()]`
&array[..]
// Same as &array[..]`
&array
A program can access an element in a slice using the same notation [i]
as accessing an element in an array.
At compile time, the size of an array is known, but the size of a slice is unknown.
Tuples
The tuple type (T1, T2, ..., Tn)
contains a sequence of elements where each element may be a different type. For example:
// Empty tuple
()
// Single-element tuple must end with `,` to distinguish it from a parenthesized expression
(1,)
// A tuple of two elements
(1, "a")
A program can access the i
th element in a tuple using the expression .i
(the index starts from 0), e.g.:
assert_eq!(("Hello", "World").1, "World");
The empty tuple ()
, also called the "unit type", is special. It has a single value ()
and is used to represent "no value". E.g., when an expression or function returns no value, it returns ()
.
Properties of composite primitive types
Two array types [T1; N1]
and [T2; N2]
are considered to be identical if T1==T2
and N1==N2
. Two tuple types (A1, A2, ..., An)
and (B1, B2, ..., Bn)
are considered to be identical if A1==B1
, ..., An==Bn
.
Composite primitive types automatically implement the Copy
trait if all their constituent types implement the Copy
trait.
Custom types
We will discuss custom types in later chapters.