The problem you've got is that you're doing something that's undefined in the language. When you declare a const anything you're saying to the compiler "I'm not going to modify this." As soon as you do something that might modify it through pointer chicanery all bets are off and you're into the teritory of....
drum roll.... undefined behaviour.
So when you take the address or a reference to a const object and then try and write through it just about anything can happen. Remember that when you do a cast you're telling the compiler you know better and it should do what you tell it. This is the compiler getting it's revenge and telling you "Ah ha foolish C programmer [1], you have entered the domain of Bjarne, feel his mockery!!"
C++ isn't like C. When you create a const in C you're saying "make a variable but make it read only." In C++ you're saying "This name is an alias for that value." Taking the address of a constant is different as well. In C you're saying "give me the address of that variable, I want to read from it through a level of indirection." In C++ you're saying "I want to use that value as if it were a real readonly variable" (usually for a function call) and the compiler obliges. It creates a temporary of the right type and gives you it's address. So while casting away const on a const variable might work in C it's undefined (i.e. bad) when you do it in C++.
To put that in C terms what you're doing is:
const int x = 10;
int y = x;
int *p = &y;
Except you never see y.
Incidentally had you done something like:
void set_to_20( const int *p )
{
*const_cast<int *>( p ) = 20;
}
int main()
{
const int x = 10;
int y = 10;
set_to_20( &x );
set_to_20( &y );
std::cout << x << '\t' << &x << std::endl;
std::cout << y << '\t' << &y << std::endl;
}
you'll see that you can safely cast away const from &y as it refers to a non-const int but not from &x as there is no variable called x to write to.
Now you know what's going on with Microsoft's compiler, don't rely on it. While MS use a fairly orthodox way of interpreting the standard here but there are other things that a compiler might do that could sink you without a trace. One is (for example) sticking the temporary in read only memory and crashing your code when it tries to write.
Er, anyway. That's me whittering on enough. Ooo, couple of more points...
- main returns an int in both C and C++. If it doesn't then anything can happen. Returning void is only good for being mocked by programmers that want to write standard code that compiles on more than one compiler, it has no other utility.
- (int *) is so 1990s - consider what you want your cast to do and use either static_cast (converting compatible values), reinterpret_cast (fitting the bits into a new mould) or const_cast (removing const or volatile).
Cheers,
Ash
[1] Don't deny it, taking addresses of consts and using C style casts are a dead giveaway. And if some lecturer or instructor is telling you that's idiomatic C++ ask for your money back.
PS: Eugen said in a comment that you never see the address of y. Actually you do. It's what the compiler says is the address of x. You can't see the address of x because x hasn't got an address, it's just an alias which is why the compiler creates y.