Constants & Statics
Constants and statics are Rust's two ways to declare fixed, named values — a const is a compile-time value inlined at every use, while a static is a single value with a fixed memory location that lives for the whole program.
Learn Constants & Statics in our free Rust course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Rust course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll learn const vs static , naming conventions, const fn and compile-time evaluation, the lifetime, and how shadowing differs from a constant.
What You'll Learn in This Lesson
1️⃣ const: Compile-Time Constants
A const declares a value fixed at compile time. You must annotate its type, the value must be a constant expression, and the convention is SCREAMING_SNAKE_CASE . The compiler inlines the value wherever you use it, so it behaves like a named literal — and you can declare one at module scope or inside a function.
Constants are perfect for magic numbers, configuration limits, and mathematical values. Naming them gives the number meaning and a single place to change it.
2️⃣ static & const fn
A static also names a fixed value, but unlike const it has a single memory address and the lifetime — it exists for the entire program. A const fn is a function the compiler can run at compile time , so its result can initialize a const .
3️⃣ Shadowing vs const
Shadowing reuses a variable name with a fresh let , creating a brand-new binding that can even change the type. That's quite different from a const , which is one fixed value with one type. Don't confuse shadowing with mut either — shadowing makes a new binding, while mut changes the existing one.
Your turn. Fill in the blanks marked ___ , then run it.
Compose constants and a const fn so the compiler does the arithmetic before your program even runs. Run it with cargo run and check the output.
📋 Quick Reference — Constants & Statics
Practice quiz
What must you always provide when declaring a const?
- The mut keyword
- A lifetime
- An explicit type annotation
- A trait bound
Answer: An explicit type annotation. A const cannot infer its type, so you must annotate it, e.g. const MAX: u32 = 100;.
What is the conventional naming style for const and static items?
- SCREAMING_SNAKE_CASE
- camelCase
- snake_case
- PascalCase
Answer: SCREAMING_SNAKE_CASE. Constants and statics conventionally use SCREAMING_SNAKE_CASE.
How does a const differ from a static in memory?
- A const has a fixed address; a static is inlined
- Both have one address
- Both are inlined identically
- A const is inlined at each use; a static has one fixed memory address
Answer: A const is inlined at each use; a static has one fixed memory address. A const is inlined wherever used; a static lives at a single fixed address for the whole program.
What does the 'static lifetime mean?
- The value is mutable
- The value lives for the entire duration of the program
- The value is on the stack
- The value is dropped immediately
Answer: The value lives for the entire duration of the program. 'static means the data lives for the whole program, so references to it are valid forever.
What is a const fn?
- A function the compiler can evaluate at compile time
- A function that cannot be called at runtime
- A constant that acts like a function
- A function returning only constants
Answer: A function the compiler can evaluate at compile time. A const fn can run at compile time (and still at runtime), so it can initialize a const.
What does this print? const fn square(n: u32) -> u32 { n * n } const NINE: u32 = square(3); fn main() { println!("{}", NINE); }
- 3
- 6
- 9
- It does not compile
Answer: 9. square(3) is evaluated at compile time to 9 and stored in NINE.
What does this print? const fn seconds_in_hours(h: u32) -> u32 { h * 60 * 60 } const DAY: u32 = seconds_in_hours(24); fn main() { println!("{}", DAY); }
- 1440
- 86400
- 3600
- 24
Answer: 86400. 24 * 60 * 60 = 86400 seconds in a day, computed at compile time.
What is shadowing?
- Mutating a variable in place
- Hiding a const
- Declaring a static
- Reusing a name with let to create a brand-new binding, possibly a new type
Answer: Reusing a name with let to create a brand-new binding, possibly a new type. Shadowing makes a new binding with let that hides the old one and can change type.
What does this print? let value = "42"; let value: i32 = value.parse().unwrap(); println!("{}", value + 10);
- 4210
- 52
- 42
- It does not compile
Answer: 52. Shadowing turns the &str into i32 42, and 42 + 10 is 52.
Why is a static mut considered unsafe to access?
- It is too slow
- It cannot be typed
- Shared mutable global state is not thread-safe
- It has no address
Answer: Shared mutable global state is not thread-safe. Accessing static mut requires unsafe because shared mutable globals invite data races; prefer Mutex or atomics.