In general const is 100% compiler. When you declare something const, the compiler places restrictions on what it will let you write. It won't let you assign to const scalar, assign through a const reference or or pointer, or invoke a non-const function of const object.
There is no guarantee that the compiler will arrange any sort of runtime protection.
This is actually a very complicated thing in an optimizing compiler. It starts out simple, though.
When you declare a variable with the const keyword (let's just ignore pointers because they can be const or point to const or both) the compiler remembers that no code should be changing that variable (almost). If the compiler sees code that changes a const variable then it considers that an error (or occasionally only worthy of a warning, but for simplicity sake I'll ignore it). The compiler also assumes that no code that it cannot see (right now anyway {code in other .c files or possibly library or .s or .asm files) will change the const variable (unless it is const volatile in which case it will assume that it could change at any moment, but will still enforce not letting your code change it -- this is useful for memory mapped SFR [special function registers] that are used to read a device's state, but can't be written to. Remember that c and c++ are used for OS and embedded programming).
The assumption that a variable will not change under some or all circumstances allows the compiler's optimization routines to do things that it otherwise wouldn't be able to do. This means stuff like placing the literal value of a variable into the instruction stream rather than loading the variable's address and then loading the variable's value. It can also assume that if it loaded that if:
extern const int foo; // note that the value isn't visible, so a load is necessary
...
extern int baz(int, int);
...
int bar(int x, int y) {
int m, n;
int r = x / foo; // this would require loading the value of foo from RAM
m = baz(r, y); // the compiler normally has to assume that a function could change a global
n = m + r + foo; // but since the global foo is const it shouldn't be able to be changed
// by the call to baz and does not need to be reloaded
return n;
}
An executable file (o