I know this from RFC 246:
- constants declare constant values. These represent a value, not a memory address. This is the most common thing one would reach for and would replace
static
as we know it today in almost all cases.
- statics declare global variables. These represent a memory address. They would be rarely used: the primary use cases are global locks, global atomic counters, and interfacing with legacy C libraries.
I don't know what is actually different between the two when I try to maintain a table.
Which one should I choose?
Mutability
A const
variable in Rust is immutable. You neither can reassign nor modify it:
struct Foo(u32);
const FOO: Foo = Foo(5);
fn main() {
FOO = Foo(1); //illegal
FOO.0 = 2; //illegal
}
A static
variable can be mutable and therefore can either be modified or reassigned. Note that writing/modifying a global static
variable is unsafe and therefore needs an unsafe
block:
struct Foo(u32);
static FOO: Foo = Foo(5);
static mut FOO_MUT: Foo = Foo(3);
fn main() {
unsafe {
FOO = Foo(1); //illegal
FOO.0 = 2; //illegal
FOO_MUT = Foo(1);
FOO_MUT.0 = 2;
}
}
Occurrences
When you compile a binary, all const
"occurrences" (where you use that const
in your source code) will be replaced by that value directly.
static
s will have a dedicated section in your binary where they will be placed (the BSS section, see Where are static variables stored in C and C++? for further information).
All in all, stick to a const
whenever possible. When not possible, because you need to initialize a variable later in the program of with non-const
methods, use lazy_static!
.
There's not much practical difference if your variable isn't intended to change.
Constants are inlined at compilation, which means they're copied to every location they're used, and thus are usually more efficient, while statics refer to a unique location in memory and are more like global variables.
Constants are... constant while statics, while still global, can be mutable.
The main purpose of static
is to allow functions to control an internal value that is remembered across calls, but not be accessible by the main application code. It is similar to Class variables as opposed to Instance variables in other languages. Also C and PHP and many other languages have this concept.
Example: you want to track how many times a function is called and have a way of resetting the internal counter:
fn counter(reset: bool) -> i32 {
static mut Count: i32 = 0;
unsafe {
if reset {
Count = 0;
}
Count += 1;
return Count;
}
}
println!("{}",counter(true));
println!("{}",counter(false));
println!("{}",counter(false));
//println!("{}", Count); // Illegal