What is the result of the reference operator "&" on constant variables?

I was asked how to change the value of a constant variable.

My obvious answer was "pointers!". but I tried the following code snippet and I am puzzled ...

int main() { const int x = 5; int *ptr = (int *)(&x); // "Cast away" the const-ness.. cout << "Value at " << ptr << ":"<< (*ptr) <<endl; *ptr = 6; cout << "Now the value of "<< ptr << " is: " << (*ptr) <<endl; cout << "But the value of x is still " << x <<endl; return 0; } 

And the result was:

 Value at <some address> :5 Now the value of <same address> is: 6 But the value of x is still 5 

Now I'm not sure exactly what is returned from '& x', but this is definitely not the actual address of x, since the value in x has not been changed!

But on the other hand, ptr did contains the value x at the beginning! So what is it?

EDIT compiled with VS2010

+7
source share
5 answers

Your program invokes undefined behavior (writing to a constant variable using a pointer is undefined behavior), so anything can happen. This, as they say, is the most likely explanation for why you get the behavior that you see in your specific implementation:

When you execute &x , you get the address x . When you do *ptr = 6 , you write 6 to x memory location. However, when you execute cout << x , you are not actually reading from memory x , because your compiler has optimized the code by replacing x with 5 here. Since x is const , the compiler is allowed to do this because there is no legitimate C ++ program in which this will change the behavior of the program.

+15
source

The compiler caches x in the register, so the value in memory changes, but the last printout is still the same. Check the generated assembly (compile with -s ).

+2
source

First of all, this behavior is undefined. However, here is what probably happens:

When you do this:

 int *ptr = (int *)(&x); 

5 is stored at some address somewhere. This is why the pointer works correctly. (although dropping a constant is still undefined)

However, due to compiler optimization, x = 5 simply inserted as a literal into the final print statement. The compiler considers this safe because x declared const .

 cout << "But the value of x is still " << x <<endl; 

This is why you print the original value of 5.

+2
source

Perhaps you are faced with a side effect of code optimization, try running the same code by disabling all optimization or checking the code generated by asm. I assume that the compiler reuses the value that it has in some registry by function, because it relies on a constant, so even if you really change the value, the changed value does not propagate properly. The reasons Kate noticed in comemnts is because you are looking at undefined behavior.

+1
source

What is returned from &x is a pointer to const int (i.e. int const* ). Pointers are currently implemented with address preservation, but pointers are not addresses, and your example shows quite well: the type of pointer, even if it is not at run time, still plays an important role.

In your case, you drop const and thus lie to the compiler "this pointer points to a non-constant int". However, the compiler knows from the declaration that the value of x cannot change (it was declared const) and freely uses this fact (and the standard allows this: your attempt to change it with a pointer to a non-const int is undefined behavior, and therefore the compiler is allowed that anything to do).

0
source

All Articles