Skip to main content
Rust Programming
CHAPTER 04 Beginner

Variables, Constants, and Data Types

Updated: May 18, 2026
5 min read

# CHAPTER 4

Variables, Constants, and Data Types

1. Chapter Introduction

In this chapter, we will learn how to store and manipulate data in Rust. Rust handles variables very differently from languages like Python or JavaScript. To ensure safety and prevent bugs, variables in Rust are Immutable (unchangeable) by default. We will explore how to override this behavior, how to define Constants, and survey the fundamental Data Types that Rust provides.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Declare variables using the let keyword.
  • Understand and utilize Immutability by default.
  • Make variables mutable using the mut keyword.
  • Declare Constants using const.
  • Differentiate between Scalar types (integers, floats, booleans, chars) and Compound types (tuples, arrays).

3. Variables and Immutability

To declare a variable in Rust, use the let keyword.

CRITICAL RULE: By default, once a value is bound to a variable name, you cannot change it! This is called Immutability. It makes your code incredibly safe, especially in multi-threaded programs.

rust
123456
fn main() {
    let x = 5;
    println!("The value of x is: {}", x);
    
    // x = 6; // ERROR! Cannot assign twice to immutable variable `x`
}

If you want a variable to be changeable, you must explicitly add the mut (mutable) keyword.

rust
1234567
fn main() {
    let mut y = 10; // 'mut' allows the value to change
    println!("Initial y: {}", y);
    
    y = 20; // This is now perfectly fine!
    println!("Updated y: {}", y);
}

4. Constants

Constants are values that are bound to a name and are *never* allowed to change. Differences between let and const:
  1. 1. You use const instead of let.
  1. 2. You CANNOT use mut with const.
  1. 3. You MUST explicitly declare the data type.
  1. 4. Constants can be declared in the global scope (outside of main).
rust
123456
// Standard convention is UPPERCASE_WITH_UNDERSCORES
const MAX_SPEED: u32 = 120; 

fn main() {
    println!("Max speed is {}", MAX_SPEED);
}

5. Data Types in Rust

Rust is a Statically Typed language, meaning it must know the types of all variables at compile time. Usually, the compiler can infer the type based on the value, but sometimes we must specify it explicitly.

#### A. Scalar Types A scalar type represents a single value. Rust has four primary scalar types:

1. Integers (Whole numbers)

  • Signed (can be negative): i8, i16, i32, i64, i128, isize
  • Unsigned (positive only): u8, u16, u32, u64, u128, usize
*(Default is i32)*

rust
1
let age: u8 = 25; // Explicit type annotation

2. Floating-Point Numbers (Numbers with decimals)

  • f32 (Single precision)
  • f64 (Double precision)
*(Default is f64)*

rust
12
let price = 19.99; // Defaults to f64
let weight: f32 = 4.5;

3. Booleans Can only be true or false.

rust
1
let is_active: bool = true;

4. Characters (char) Represents a single Unicode value (uses single quotes).

rust
12
let letter: char = 'R';
let emoji = '🚀'; // Emojis are valid characters!

#### B. Compound Types Compound types group multiple values into one type. Rust has two primitive compound types:

1. Tuples Group values with a *variety of different types* into one compound type. Tuples have a fixed length.

rust
123456789101112
fn main() {
    // Tuple of (string, integer, float)
    let person: (&str, i32, f64) = ("Alice", 30, 5.5);
    
    // Access using dot notation and the index
    println!("Name: {}", person.0);
    println!("Age: {}", person.1);
    
    // Destructuring a tuple
    let (name, age, height) = person;
    println!("Destructured: {} is {}", name, age);
}

2. Arrays Group multiple values of the *exact same type*. In Rust, arrays have a fixed length (they cannot grow or shrink).

rust
1234567891011
fn main() {
    // Array of 5 integers
    let numbers: [i32; 5] = [1, 2, 3, 4, 5];
    
    // Access using square brackets
    println!("First number: {}", numbers[0]);
    
    // Initialize an array with the same value repeated
    // Creates [0, 0, 0, 0, 0]
    let zeroes = [0; 5]; 
}

6. Variable Shadowing

You can declare a new variable with the same name as a previous variable. This "shadows" the original variable, effectively replacing it. Unlike mut, shadowing allows you to change the *Data Type*.
rust
123456
fn main() {
    let spaces = "   "; // String type
    let spaces = spaces.len(); // Re-declared as an integer!
    
    println!("There are {} spaces", spaces);
}

7. Common Mistakes

  • Mutating a non-mut variable: Trying to change a variable declared with just let is the most common beginner error.
  • Out of bounds Array access: Attempting to access numbers[10] on an array of length 5 will cause the program to "panic" (crash) safely, rather than allowing hackers to read arbitrary memory like in C/C++.
  • Mismatched types: Rust will NOT automatically convert a float to an integer. You cannot do let x: i32 = 5.5;.

8. Best Practices

  • Embrace Immutability: Only use mut when you absolutely need to. Code with immutable variables is easier to read, test, and run concurrently without bugs.
  • Let the compiler infer types: You don't need to write let x: i32 = 5;. Just write let x = 5; and let Rust figure it out to keep your code clean.

9. Exercises

  1. 1. Create a mutable integer score set to 0. Add 10 to it and print it.
  1. 2. Create a constant PI with the value 3.14159.
  1. 3. Create a tuple representing a 3D coordinate (x, y, z) and print the y value using dot notation.

10. MCQs with Answers

Question 1

By default, variables in Rust are:

Question 2

Which keyword allows a variable to be changed?

Question 3

How do you declare a constant in Rust?

Question 4

What is the default integer type in Rust if not specified?

Q5. Can a Rust Array grow in size after it is created? a) Yes b) No, arrays have a fixed length Answer: b) No, arrays have a fixed length.
Question 6

What Compound type allows you to group variables of DIFFERENT data types?

Question 7

How do you access the first element of a Tuple named my_tuple?

Question 8

What feature allows you to declare a new variable with the same name as a previous one, even changing its data type?

Question 9

Which scalar type represents a single Unicode character enclosed in single quotes?

Q10. Will the compiler allow let age: u8 = -5;? a) Yes b) No, because u8 is an unsigned integer and cannot be negative Answer: b) No, because u8 cannot be negative.

11. Interview Questions

  • Q: Explain the difference between mut and Shadowing.
  • Q: Why did the creators of Rust make variables immutable by default?
  • Q: What is the difference between an Array and a Tuple in Rust?

12. FAQs

  • When should I use i32 vs u32? Use i32 for general numbers that might be negative. Use u32 (unsigned) when you want to mathematically guarantee the value can never drop below zero (like an age or a counter).

13. Summary

Rust's strict type system and immutability by default are the foundations of its safety guarantees. By forcing you to explicitly declare when data will change using mut, Rust prevents accidental modifications. Understanding scalar and compound types allows you to organize data efficiently in memory.

14. Next Chapter Recommendation

Now that we have data, we need to do math and logic with it. In Chapter 5: Operators and Expressions in Rust, we will explore arithmetic, logical comparisons, and the critical distinction between Statements and Expressions in Rust.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·