Data Type#

Every value in Rust has a Data type.
Since Rust is a statically typed language, the Data type must be determined at compile time.

1. Scalar type#

A Scalar type represents a single value, and there are four kinds of Scalar types.

1.1 integer#

The integer type is used for whole numbers and cannot include decimal points.
The kinds of integer types are shown in the table below.

SizeSignedUnsigned
8-biti8u8
16-biti16u16
32-biti32u32
64-biti64u64
128-biti128u128
archisizeusize

Here, i represents a signed integer, which can use both positive and negative numbers.
u is an unsigned integer, which can only use positive numbers.
Since signed integers use 1 bit for the sign, their range of representable values is smaller than that of unsigned integers.
The range of representable values can be calculated using the following formula, where $n$ represents the number of bits used.

  • Signed : from $-(2^{n-1})$ to $2^{n-1}-1$
  • Unsigned : from $0$ to $2^{n}-1$

For example, i8 can represent values from $-(2^{7})=-128$ to $2^{7}-1=127$,
and u8 can represent values from $0$ to $2^{8}-1=255$.
 
arch uses 32-bit for computers with a 32-bit architecture and 64-bit for computers with a 64-bit architecture.
 
※ Integer overflow
If a value exceeds the representable range, one of the following two cases occurs.

  • Debug mode : A panic occurs and the program terminates. (For example, storing 256 in a u8 variable causes a panic.)
  • Release mode : The value wraps around to the minimum value of the range. (For example, storing 256 in a u8 variable overflows and becomes 0.)

1.2 floating-point#

In Rust, the Floating point type is used to represent real numbers with decimal points.
There are two Floating point types: f32, which is 32-bit in size, and f64, which is 64-bit in size.

When the type is not specified as in the following code, it defaults to f64.

    let apple = 1.234;   // f64

To use f32, you must specify it as :f32 as in the following code.

    let apple:f32 = 1.234;   // f32

1.3 boolean#

The Boolean type can only have true or false values, and is 1 byte in size.
You can create a Boolean type variable as shown in the following code.

    let apple = true;
    let apple:bool = true;

1.4 char#

A char represents a single character and uses single quotes ('a').
     ※ Using double quotes ("a") makes it a string, not a char.

A Rust char is a Unicode scalar value, 4 bytes in size, and can store multilingual characters and emojis.
     ※ Do not confuse this with the 1-byte char type in C/C++.

You can create a char type variable as follows.

    let banana = 'A';
    let banana:char = 'A';
    let banana = '김';
    let banana = '🐱';

 

2. Compound type#

A Compound type can bundle multiple types of values into one.
I will explain two types: tuple and array.

2.1 tuple type#

You can use parentheses ( ) to combine values of various types into a tuple, as shown in the following code.
Once a tuple is declared, its size cannot be changed.

    let apple: (i32, f32, char) = (10, 1.23, 'A');
    let banana = (10, 1.23, 'A');

You can destructure a tuple as in let (a, b, c) = banana; in the following code.

    let banana = (10, 1.23, 'A');
    let (a, b, c) = banana;
    let sum = a + b;

    println!("a = {a}");
    println!("b = {b}");
    println!("c = {c}");
    println!("a + b = {sum}");

Here is the execution result.

a = 10
b = 1.23
c = A
a + b = 11.23

A tuple can be accessed using .index as shown in the following code.
banana.0 points to 10, and banana.1 points to 1.23.
The index of the first element is 0.

    let banana = (10, 1.23, 'A');

    println!("index 0 = {0}", banana.0);
    println!("index 1 = {0}", banana.1);
    println!("index 2 = {0}", banana.2);

Here is the execution result.

index 0 = 10
index 1 = 1.23
index 2 = A

If you go out of the tuple’s index range, as in banana.99 in the following code, an error is raised at compile time, not at runtime.
This can improve the runtime stability of the software.

    let banana = (10, 1.23, 'A');
    println!("index 2 = {0}", banana.99);

Here is the execution result.

error[E0609]: no field `99` on type `({integer}, {float}, char)`
 --> code1.rs:5:38
  |
5 |     println!("index 2 = {0}", banana.99);
  |                                      ^^ unknown field

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0609`.

2.2 array type#

An array is composed only of elements of the same type and has a fixed length.
Let’s look at some ways to create arrays.
The following code is an example of creating an array with three int-type elements: 1, 2, 3.

    let arr = [1, 2, 3];

You can create an array by specifying the type and size as shown in the following code.

    let arr:[i32; 3] = [1, 2, 3];

When accessing an element of an array, you can use an index as in arr[0] in the following code.

    let arr = [1, 2, 3];

    println!("{}", arr[0]);
    println!("{}", arr[1]);

If you hard-code an index out of the array’s range, such as arr[9] in the following code, the compiler raises an error at compile time.
This helps prevent runtime errors in advance.

    let mut arr = [1, 2, 3];

    arr[9] = 99;

Here is the execution result.

error: this operation will panic at runtime
  --> code1.rs:10:5
   |
10 |     arr[9] = 99;
   |     ^^^^^^ index out of bounds: the length is 3 but the index is 9
   |
   = note: `#[deny(unconditional_panic)]` on by default

error: aborting due to 1 previous error

However, when the index is not hard-coded but is a variable, as in the following code, no error is raised at compile time.
A panic is raised at runtime instead.

    let mut arr = [1, 2, 3];

    for i in 10..20 { 
        arr[i] = 99;
    }

Here is the execution result.

thread 'main' panicked at code1.rs:7:9:
index out of bounds: the len is 3 but the index is 10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace