Why can you kind of cheat compiler this way:
const int a = 5; *((int*)&a)=5; // VC/armcc does not complain when above is "abridged" equivalent of this:
const int *ptr2const = &a; int *ptr = ptr2const; // as expected error is raised here *ptr = 5; Why can you kind of cheat compiler this way:
const int a = 5; *((int*)&a)=5; // VC/armcc does not complain when above is "abridged" equivalent of this:
const int *ptr2const = &a; int *ptr = ptr2const; // as expected error is raised here *ptr = 5; Casting is your way of telling the compiler "I know what I'm doing", so it doesn't complain. Unfortunately, in this instance, you will invoke undefined behaviour.
C-style casts allow you to cast away constness like in your example. In C++, you would normally use the new style casts such as static_cast<>, which don't allow you to cast away constness. Only const_cast<> allows you to do that.
C-style casts, such as (int*) are equivalent to C++ const_cast in their ability to cast away constness, so you can side-step const-correctness by using them, although such use is unrecommended (can lead to undefined behaviour).
int main() { const int x = 1; (int&)x = 2; std::cout << x << std::endl; } On my system, the above writes 1 to stdout. You might experience different behaviour.
On the other hand...
void foo(const int& x) { (int&)x = 2; } int main() { int x = 1; foo(x); std::cout << x << std::endl; } This writes 2 for me. The difference is that the const used in foo is const as a type qualifier, while in the main in the first example it was used as a storage class. It's not always easy to see whether a variable was declared with const as a storage class, so it's best not to rely on a const_cast or C-style cast to cast away const.
It's best just to use static_cast in most situations as this will warn you at compile time of any suspect behaviour in the form of a compile error.
const_cast. The reason for C++ having different cast syntaxes for casts of different nature is precisely to avoid accidentally invoking an invalid cast like this.This only "works" because the variable is local, and implementations have no way to enforce const-ness on a local (automatic) variable in general (at least not if the address of the variable is ever taken). But as far as the language specification is concerned, this is in the realm of undefined behavior.
If you try this on a global/static variable, you'll quickly find that most implementations can and do enforce const by putting the variable in read-only memory which can be shared between multiple instances of your program.