HiveBrain v1.2.0
Get Started
← Back to all entries
gotcharustMajor

What is the difference between a constant and a static variable and which should I choose?

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
constantshouldandbetweenthedifferencechoosevariablestaticwhat

Problem

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?

Solution

Mutability

A constant in Rust is immutable. You neither can reassign nor modify it:
struct Foo(u32);

const FOO: Foo = Foo(5);
const mut FOO: Foo = Foo(5); // illegal

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.

statics 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!.
Interior mutability

While both const and static can use interior mutability you should never ever do it with a const. Here's an example
use std::sync::atomic::{AtomicU32, Ordering};

static STATIC: AtomicU32 = AtomicU32::new(0);
const CONST: AtomicU32 = AtomicU32::new(0);

fn print() {
println!("static: {}", STATIC.load(Ordering::Relaxed));
println!("const: {}", CONST.load(Ordering::Relaxed));
}

fn main() {
STATIC.store(3, Ordering::Relaxed);
CONST.store(3, Ordering::Relaxed);

print();
}


This compiles fine without any warnings, but leads to unwanted behavoir. Output:
static: 3
const: 0


When using clippy, it will show the two following warnings:
warning: a const item should never be interior mutable
--> src/main.rs:4:1
|
4 | const CONST: AtomicU32 = AtomicU32::new(0);
| -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| make this a static item (maybe with lazy_static)
|
= note:
#[warn(clippy::declare_interior_mutable_const)] on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#declare_interior_mutable_const

warning: a
const item with interior mutability should not be borrowed
--> src/main.rs:8:27
|
8 | println!("const: {}", CONST.load(Ordering::Relaxed));
| ^^^^^
|
= note:
#[warn(clippy::borrow_interior_mutable_const)] on by default
= help: assign this const to a local or static variable, and use the variable here
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const

warning: a
const item with interior mutability should not be borrowed
--> src/main.rs:13:5
|
13 | CONST.store(3, Ordering::Relaxed);
| ^^^^^
|
= help: assign this const to a local or static variable, and use the variable here
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const

Context

Stack Overflow Q#52751597, score: 87

Revisions (0)

No revisions yet.