4.1Introduction to fundamental data types

Last updated June 11, 2026

Chapter introduction

Chapter 1 used types on faith: numbers were "integers," the compiler knew best. This chapter ends the faith-based era. You'll meet Rust's fundamental types properly (integers in all their sizes, floating-point numbers, booleans, characters, tuples), learn what they cost and where they fail, and pick up if along the way, because quizzes about types are dull until programs can make decisions.

Lesson 1.3 pictured memory as a row of numbered boxes. Time to zoom all the way in.

Bits and bytes

The smallest unit of memory is a bit: a single 1-or-0. Memory is organized into bytes of 8 bits each, and the byte is the unit with an address; when lesson 1.3 said "numbered boxes," the boxes were bytes. Everything your programs store (every variable, every string, eventually every video frame) is some number of bytes, which is to say: a heap of 1s and 0s.

Which raises the question this whole chapter answers. If memory is nothing but bits, what makes some bits a number and others a letter?

A type is an interpretation

Nothing in memory says what the bits mean. The byte 0100 0001 is just the byte 0100 0001. Read it as an unsigned number and it's 65. Read it as text and it's 'A' (we'll see why in lesson 4.8). Read it as part of a larger float and it's a fragment of something else entirely.

A data type is the missing instruction: it tells the compiler how many bytes a value occupies and how to interpret the bits in them. When you write let x: i32 = 65;, the type i32 is what makes the stored bits mean sixty-five, makes x + 1 produce 66 rather than gibberish, and makes println! render it as 66 on your screen. The bits hold the data; the type holds the meaning. The compiler tracks both, at compile time, for everything (lesson 1.3's promise, now with a mechanism).

Size is part of the type

Each type also fixes exactly how many bytes it uses, and Rust will happily tell you:

fn main() {
    println!("bool: {} byte", size_of::<bool>());
    println!("char: {} bytes", size_of::<char>());
    println!("i32:  {} bytes", size_of::<i32>());
    println!("f64:  {} bytes", size_of::<f64>());
}
bool: 1 byte
char: 4 bytes
i32:  4 bytes
f64:  8 bytes

(size_of is a standard-library function with a new syntax wrinkle, the ::<T> part, which hands it a type instead of a value. File the wrinkle away; it returns in chapter 15.)

Why care about sizes? Because size determines range. With n bits you can form 2ⁿ distinct patterns: 1 bit gives 2 values, 8 bits give 256, 32 bits give 4,294,967,296. A type's size is therefore a hard ceiling on how many different values it can represent, and the whole integer story of the next three lessons is about choosing your ceiling.

Key insight

In Rust, the size is in the name: i32 is 32 bits, u8 is 8, always, on every machine. This sounds too obvious to be a feature until you learn the C++ situation: there, int guarantees only a minimum size and varies by platform, a whole family of fixed-width retrofit types exists to patch that, and learncpp.com spends three lessons navigating the resulting thicket. This course spends this paragraph. When a Rust program compiles on your laptop and runs on a server, the numbers are the same sizes in both places, by definition.

The cast of the chapter

Rust's fundamental scalar types, as a map of what's coming: integers in two flavors, signed i8 i16 i32 i64 i128 and unsigned u8 u16 u32 u64 u128, plus the pointer-sized pair isize/usize (lessons 4.2 through 4.4); floating-point f32/f64 for fractional values (4.5); bool (4.6); and char (4.8). Tuples (4.11) then group values together, and your old friend () turns out to have been a tuple all along.

Text strings are conspicuously absent from the list: they're built out of fundamental pieces rather than being one (chapter 5 starts that story). And readers wondering about C++'s void: Rust doesn't have it; the unit type from lesson 1.11 already does its job, and did it with a value.

Quiz time

Question #1

What is a bit, what is a byte, and which one has an address?

Show solution

A bit is a single binary digit (1 or 0); a byte is 8 bits; the byte is the addressable unit of memory.

Question #2

In your own words: what two things does a data type tell the compiler about a value?

Show solution

How many bytes the value occupies, and how to interpret the bits in those bytes (the same bits mean different things under different types).

Question #3

How many distinct values can 8 bits represent? And if those values are used for the non-negative numbers starting at 0, what's the largest one?

Show solution

2⁸ = 256 distinct values; counting from 0, the largest is 255. (You've just derived the range of u8, one lesson early.)

Next: the integer family in full, and how to choose among ten siblings.