d

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

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

a. integer

An integer is a type used for whole numbers and cannot include decimal points.
The types of integer are as follows in the table below.

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

In this context, i represents a signed integer which can use both positive and negative numbers.
u is an unsigned integer that 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 nn represents the number of bits used.

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

For example, i8 can represent values from (27)=128-(2^{7}) = -128 to 271=127,andu8canrepresentvaluesfrom2^{7} - 1 = 127, and `u8` can represent values from 0toto2^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 the range of values is exceeded, the following two scenarios occur:

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

b. floating-point

In Rust, floating point types are used to represent 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

If you need to use f32, you must specify it as :f32 as in the following code.

    let apple:f32 = 1.234;   // f32

c. 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;

d. char

In Rust, a 'char' represents a single character and uses single quotes ('a').
     ※ Using double quotes ("a") signifies a string, not a char.

A Rust 'char' is a Unicode scalar value and is 4 bytes in size, capable of storing multilingual and emoji characters.      ※ Do not confuse this with the 1-byte 'char' type in C/C++.

Here is how you can declare a char type variable:

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

 

2. Compound type

Compound types can bundle multiple types of values into one.
I will explain two types of these: tuples and arrays.

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');

In the following code, you can destructure a tuple like let (a, b, c) = banana;.

    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}");

Execution Result

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

In the following code, tuples can be accessed using .index.
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);

Execution Result

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

If, as in the code banana.99, accessing an index out of the range of a tuple causes an error during the Compile stage rather than at Runtime.
This can enhance the Runtime stability of the software.

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

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 elements of type int: 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 like arr[0] in the following code.

    let arr = [1, 2, 3];

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

If you hard-code an index that is out of the Array's range, such as arr[9], the compiler will generate an error during the compilation process.
This helps prevent runtime errors in advance.

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

    arr[9] = 99;

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 hardcoded but a variable, as in the following code, it does not cause a compile-time error.
Instead, it results in a panic at runtime.

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

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

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