Rust Data Types Examples

Rust Data Type

Learn about data types in Rust using this tutorial and examples.

[lwptoc]

What is a Data Type?

A data type tells Rust compiler the kind of data being defined.

Are data types specification mandatory in Rust?

Yes. This is because Rust is a statically typed language. This implies that it must know the types of all variables at compile time.
However the compiler can usually infer what type we want to use based on the value and how we use it.

In cases when many types are possible, we must add a type annotation, like this:

let guess: u32 = "42".parse().expect("Not a number!");

Data Types in Rust can be divided into two subsets:

  1. Scalar
  2. Compound.

What is a Scalar Type?

A scalar type represents a single value.

What are the subcategories of Scalar type?

Rust has four primary scalar types:

  1. integers
  2. floating-point numbers
  3. Booleans
  4. characters. .

What are Integer Types?

An integer is a number without a fractional component.
One type of integer type is u32 type. This type declaration indicates that the value it’s associated with should be an unsigned integer (signed integer types start with i, instead of u) that takes up 32 bits of space.

What are the integer types in rust?

Here they are:

Length Signed Unsigned
8-bit i8 u8
16-bit i16 u16
32-bit i32 u32
64-bit i64 u64
128-bit i128 u128
arch isize usize

Each variant can be either signed or unsigned and has an explicit size. Signed and unsigned refer to whether it’s possible for the number to be negative—in other words, whether the number needs to have a sign with it (signed) or whether it will only ever be positive and can therefore be represented without a sign (unsigned).

floating-point-types

Rust also has two primitive types for floating-point numbers, which are numbers with decimal points. Rust’s floating-point types are f32 and f64, which are 32 bits and 64 bits in size, respectively. The default type is f64 because on modern CPUs it’s roughly the same speed as f32 but is capable of more precision.

Here's an example of floating point type:

fn main() {
    let x = 2.0; // f64

    let y: f32 = 3.0; // f32
}

Floating-point numbers are represented according to the IEEE-754 standard. The f32 type is a single-precision float, and f64 has double precision.

Numeric Operations

Rust supports the basic mathematical operations you’d expect for all of the number types: addition, subtraction, multiplication, division, and remainder. The following code shows how you’d use each one in a let statement:


fn main() {
    // addition
    let sum = 5 + 10;

    // subtraction
    let difference = 95.5 - 4.3;

    // multiplication
    let product = 4 * 30;

    // division
    let quotient = 56.7 / 32.2;

    // remainder
    let remainder = 43 % 5;
}

The Boolean Type

As in most other programming languages, a Boolean type in Rust has two possible values: true and false. Booleans are one byte in size. The Boolean type in Rust is specified using bool. For example:

fn main() {
    let t = true;

    let f: bool = false; // with explicit type annotation
}

The Character Type

So far we’ve worked only with numbers, but Rust supports letters too. Rust’s char type is the language’s most primitive alphabetic type, and the following code shows one way to use it. (Note that char literals are specified with single quotes, as opposed to string literals, which use double quotes.)

fn main() {
    let c = 'z';
    let z = 'ℤ';
    let heart_eyed_cat = '😻';
}

Compound Types

Compound types can group multiple values into one type. Rust has two primitive compound types: tuples and arrays.

The Tuple Type

A tuple is a general way of grouping together a number of values with a variety of types into one compound type. Tuples have a fixed length: once declared, they cannot grow or shrink in size.

We create a tuple by writing a comma-separated list of values inside parentheses. Each position in the tuple has a type, and the types of the different values in the tuple don’t have to be the same. We’ve added optional type annotations in this example:

fn main() {
    let tup: (i32, f64, u8) = (500, 6.4, 1);
}

The variable tup binds to the entire tuple, because a tuple is considered a single compound element. To get the individual values out of a tuple, we can use pattern matching to destructure a tuple value, like this:

fn main() {
    let tup = (500, 6.4, 1);

    let (x, y, z) = tup;

    println!("The value of y is: {}", y);
}

The Array Type

Another way to have a collection of multiple values is with an array. Unlike a tuple, every element of an array must have the same type. Arrays in Rust are different from arrays in some other languages because arrays in Rust have a fixed length, like tuples.

In Rust, the values going into an array are written as a comma-separated list inside square brackets:

fn main() {
    let a = [1, 2, 3, 4, 5];
}

To access array elements:

fn main() {
    let a = [1, 2, 3, 4, 5];

    let first = a[0];
    let second = a[1];
}

Example 1: Data Types simple example

This example will help you learn data types in Rust

Step 1: Create Project

  1. Open your Rust IDE.
  2. In the menu go to File --> Create New Project.

Step 2: Add Dependencies

Go to your Cargo.toml and modify it as follows:

[package]
name = "types"
version = "0.1.0"
authors = ["Inanc Gumus <[email protected]>"]
edition = "2018"

[dependencies]

Step 3: Write Code

Next create a file known as main.rs and add the following code:

fn main() {
    // err: parse cannot know the type of guess.
    // let guess = "42".parse().expect("Not a number!");

    // here, we tell rust that guess is an u32 variable.
    let guess: u32 = "42".parse().expect("Not a number!");
    println!("{}", guess);

    // ====================================================
    // SCALAR TYPES
    // Represent a single value.
    // ====================================================

    // INTEGERS:
    // i8 to i128 and u8 to u128
    // -> i means signed integer
    // -> u means unsigned integer

    // there are also:
    // isize and usize.
    //
    // rust determines their sizes depending on the
    // computer the compiler runs
    //
    // for example:
    // on a 64-bit computer: isize is i64 and usize is u64.
    // on a 32-bit computer: isize is i32 and usize is u32.

    // INTEGER LITERALS:
    let _ = 1_2_3; // decimal
    let _: i64 = 0xdeadbeef; // hex
    let _ = 0o444; // octal
    let _ = 0b0101_1010; // binary
    let _ = b'I'; // byte

    // run with: cargo r -q --release
    // to see the wrapping behavior.
    //
    // 255 + 1 becomes 0.
    // 1111_1111 + 1 = 0000_0000

    // let mut over: u8 = 255;
    // over += 1;
    // println!("over: {}", over);

    let _ = 2.0; // f64
    let _: f32 = 3.0; // f32
    let _ = true || false; // bool
    let _ = '💯'; // char

    // TUPLES
    let point = (10, 20.5);
    let (x, y) = point;
    println!("x: {}, y: {}", x, y);
    println!("x: {}, y: {}", point.0, point.1);

    // ARRAYS
    let days = ["Monday", "Tuesday", "Wednesday", "Thursday",
        "Friday", "Saturday", "Sunday"];
    println!("days: {}", days.join(", "));

    // each element's type is i64
    // and there are 5 elements.
    let _: [i64; 5] = [1, 2, 3, 4, 5];

    // 3 elements, each one is 1: [1, 1, 1]
    let _ = [1; 3];

    hello();
    say(10, 20);

    // {...} is an expression.
    let (x, y) = {
        let x = 1;
        (x + 1, 5) // <- here it returns a tuple: (2, 5)
    };
    say(x, y);
    say(one().0, one().1);
}

fn hello() {
    println!("hello!");
}

fn say(n: i32, m: i64) {
    println!("n: {}, m: {}", n, m);
}

fn one() -> (i32, i64) {
    (1, 2)
}

Run

Copy the code, build and run.

Reference

Here are the reference links:

Number Link
1. Download Example
2. Follow code author
3. Code: Apache 2.0 License

Related Posts

Leave a Reply

Your email address will not be published. Required fields are marked *