In this tutorial, we will learn about data types present in the Rust programming language with examples. Every variable in Rust has a specific type associated with it, which tells what kind of data this variable will store and how to deal with it. Since Rust is a statically typed language, we need to know the type of each variable at compile time. In Rust programming language we have several types of built-in data types, so we will split them into two subsets: scalar and compound.
Scalar Types
A scalar data type in rust represents a single value. Rust has four primary scalar-type data types:
- Integer
- Floating-Point
- Boolean
- Character
1. Integer Data Type
The integer data type is used to store numbers without a fractional component. The value can be either signed or unsigned and has an explicit size as shown in the table below. Signed and unsigned refers to whether a number can be negative or positive. The signed numbers are stored in 2’s complement representation.
Signed | Unsigned | Size | Range Signed | Range Unsigned |
i8 |
u8 | 8-bit | -128 to 127 | 0 to 255 |
i16 |
u16 | 16-bit | -32768 to 32767 | 0 to 65535 |
i32 | u32 | 32-bit | -2147483648 to 2147483647 |
0 to 4294967295 |
i64 | u64 | 64-bit | -263 to (263 -1) | 0 to (264 – 1) |
Each signed variant can store a number ranging from -(2n – 1) to 2n – 1 – 1 inclusive, and the unsigned variant can store a number ranging from 0 to 2n – 1 where n is the number of bits in that variant. So an i8
can store numbers from (27) to 27 – 1, which equals: -128 to 127 and u8
can store numbers from 0 to 28 – 1 which equals: 0 to 255.
Additionally, rust also contains the isize
and usize
types depending on the architecture of the computer your program is running on, which is denoted in the table as “arch”: 64 bits if you’re on a 64-bit architecture and 32 bits if you’re on a 32-bit architecture.
2. Floating-Point
Floating point types are numbers with decimal points. Rust has two primitive floating-point numbers: f32
and f64
, which are 32 bits and 64 bits in size. Floating point numbers are represented according to the IEEE-754 standards. The f32
type is a single-precision float and f64
is the double-precision float.
fn main() { let a = 2.0; // f64 type let b: f32 = 3.0; // f32 type let c: f64 = 2.0; // f64 type }
The default type in rust is f64
.
3. Boolean Type
Just like any other programming language, the boolean data type in rust can also have two possible values: true
or false
.
fn main() { let is_true = ture; let is_false: bool = false; //explicit bool type annotation }
4. Character
Rust char type is used to store a 4-byte
character. The char type is specified with single quotes, as opposed to string types that use double quotes. Since the char size in rust is 4-byte hence it can store more than ASCII characters.
fn main() { let a = 'I'; let b = 'ℤ'; let laptop_emoji = '💻'; }
Accented letters; Chinese, Japanese, and Korean characters; emoji; and zero-width spaces are all valid char
values in Rust.
Compound Types
Compound datatypes can group multiple values of the same or different types into one type. Rust generally supports two primitive compound types: tuples and arrays.
1. Tuples
A tuple helps us to group together n number of other values with different or the same types into one compound type. Tuples are constructed using parentheses ()
, and each tuple itself is a value with a type signature (T1, T2, ...)
, where T1
, T2
are the types of its members.
fn main() { let my_tuple = (100, 56.6, 'I'); let (a, b, c) = my_tuple; println!("The value of a is: {}, b is: {} and c is: {}", a,b,c); }
Output
The value of a is: 100, b is: 56.6 and c is: I
This program first creates a tuple of type (int, f64, char)
and stores it into the my_tuple
variable and then destructs it into three separate variables a, b, and c, and finally the program prints the value of the destructed variables.
2. Arrays
Just like tuple arrays also helps us to create a collection of multiple values but unlike a tuple, every element of an array must have the same type. Arrays in rust are of fixed length: once declared, their size cannot grow or shrink.
To create an array in rust, we need to place a comma-separated list of values inside the square bracket.
fn main() { let int_arr = [1, 2, 3, 4, 5]; let str_arr: [&str; 4] = ["Int", "Main", "Rust", "Tutorial"]; }
In the above program, we have created two arrays int_arr
of type i32
and str_arr
of size 4
and type &str
.
Arrays are useful when we want the data to be allocated in the stack rather than the heap or when we know the number of elements at compile time.
Accessing Array Elements
Since the array is stored in the stack, hence a single chunk of memory is allocated to it and we can access the array elements using indexing.
fn main() { let int_arr = [1, 2, 3, 4, 5]; println!("The element at 0th index is: {}" int_arr[0]); println!("The element at 0th index is: {}" int_arr[1]); println!("The element at 0th index is: {}" int_arr[2]); println!("The element at 0th index is: {}" int_arr[6]); //This will result in the panic, as 6th index is not valid }
If we try to access an element of an array that is more than the size of the array, in that case, the compilation will not produce any error but the program will result in the runtime error. When you attempt to access an element using indexing, Rust will check that the specified index is less than the array length. If the index is greater than the length, the Rust program will panic. In the above program, the int_arr[6]
will cause panic as the 6th
the index is not a valid index.