+6  A: 

I suspect that you're tripping up the compiler. It doesn't expect you to play dirty tricks with e, so when it sees the line:

cout << e << endl;

It simply inserts the value 2 instead of looking for the actual value. You can verify (or disprove) this by looking at the disassembly of your program.

Peter Ruderman
+1 for spelunking in assembly
quixoto
+2  A: 

I guess the compiler uses the constness to optimizes out the variable and insert a fixed value into the code.

extropy
+2  A: 

The only thing I can think of is the compiler has some how optimised the code in such a way that any references to e are replaced with a value of 2 even though it assigns memory for e

so in effect (affect?) the line at comment (4) is 'optimized' to be

cout << "2" << endln;
thecoshman
+3  A: 

I'm guessing that the compiler has optimised the value output. It sees that e is const (so, it can't change -- in theory) and changes cout << e << endl; to cout << 2 << endl;. However, e still has to exist because it's used by w, so w correctly takes its address and modifies its value, but you don't see that in the cout.

Moral of the story -- only declare things const when you actually want to be const. Casting away constness is not a good idea.

Peter Alexander
+13  A: 

As I said in my comment, once you modified the const value you are in undefined behaviour land, so it doesn't make much sense to talk about what is happening. But what the hell..

cout << *w << endl;            // (3) outputs 5
cout << e << endl;             // (4) outputs 2

At a guess, *w is being evaluated at runtime, but e is being treated as a compile time constant

anon
Maybe... other possibility is that the compiler noticed "*w=5" just before and inserted 5 in the first line instead of *w
jpalecek
I agree. A const int initialized in scope will be a compile time constant.
Zan Lynx
Does this mean that there's just no use casting a const variable to a non-const pointer, since modifying through that pointer results to undefined behavior?
jasonline
Pretty much, the whole point of const is that you don't modify the value... you should never, ever cast away const.
Peter Alexander
@jasonline Modifying a const object is undefined. Using a const cast to get a non-const pointer, and then using that pointer to do something like call a non-const member function is OK, provided the member function does not change the original object.
anon
@jpalecek: I think it would be a fairly obvious optimization and that in fact both are evaluated at compile time. It would be interesting to pass `w` to another (non inline) method to perform the printing and see what value is printed.
Matthieu M.
I agree with Neil, for a longer explanation `const X c = v`, where `X` is a enum or integral type, and `v` is an integral constant expression (i.e. `const int v = 5;`) defines a constant `c` that can be used as an integral constant expression itself. That means that the compiler can inline the value when compiling any use of `c`, which is what is most probably happening. The UB is that modifying that constant through a `const_cast` (the C style cast there is a `const_cast`) may do anything or nothing at all, including killing the application. In this particular case it is modifying the value.
David Rodríguez - dribeas
I just checked with a friend and, using GCC without any optimization, the result is 5 and 5 as expected, and the assembly is pretty much what you expect it to be. However, if you start using O1, you see that the compiler insert the immediate value on the stack to call printf, resulting in 5 and 2.
Gab Royer
@Gab Well, I just tried it with g++ 4.4.1 , no optimisations, and got 5 and 2. Just shows that when you are in UB land, anything can happen!
anon
I see. Thanks for all your clarifications. I thought I was missing something.
jasonline
@Neil, yeah we just checked with g++ and we get the same results as you do. The way it was calling printf was kind of weird though as it wasn't pushing value on the stack but passing it through edi and esi. Anyways, undefined behavior it is!
Gab Royer
A: 

This behaviour of compiler is misleading. It should stop constant folding once address of the constant is assigned to some other const or non-const pointer. Then for both variable single value will be printed. simple for compiler and programmer both.

umesh