2

I am trying to understand const in c++. I wrote this following code snippet:

const int x=5;
int *ptr;
ptr=(int*)&x;
cout<<"address of x="<<&x<<endl;
cout<<"value of ptr="<<ptr<<endl;
*ptr=11;
cout<<"*ptr="<<*ptr<<endl;
cout<<"x="<<x;

The output is

address of x=0x28fef8
address of ptr=0x28fef8
*ptr=11
x=5

Since ptr is pointing to x, i was sure the value of the *ptr and x would be the same. Why are the values different? I understand that x is const, however, i am changing the value at the memory address by doing *ptr . Please tell me what am i missing.

starsplusplus
  • 1,232
  • 3
  • 19
  • 32
SeasonalShot
  • 2,357
  • 3
  • 31
  • 49
  • 2
    Modifying the value of a `const` variable results in undefined behavior. – Cory Kramer Dec 02 '14 at 20:14
  • @Cyber Even if we modify the value at its address ? Why so? – SeasonalShot Dec 02 '14 at 20:16
  • 2
    Because you lied to the compiler. You told it `x` would never change, so it might have made assumptions based on that. – Fred Larson Dec 02 '14 at 20:17
  • 1
    @BoyLittUp If you modify the bytes at that address, you are technically *reusing* the storage allocated to `x`. You can do this with primitive types without calling constructors/destructors. This means that `x` is no longer valid to use. – Red Alert Dec 02 '14 at 20:20
  • @RedAlert I didn't quite get the reusing part. Could you please explain? – SeasonalShot Dec 02 '14 at 20:26
  • @RedAlert if ptr references to a brand new object, wouldn't the memory address be different? – SeasonalShot Dec 02 '14 at 20:32
  • @RedAlert What you say is correct, but unrelated. The value is declared const and as such modifying it will lead to undefined behavior, regardless of the fact that it is a primitive. Further does this code never modify bytes directly. It still invokes the assumed `operator=` of `int`. You would need placement new for that. – pmr Dec 02 '14 at 20:38
  • 1
    duplicate: http://stackoverflow.com/questions/22656734/how-is-a-variable-at-the-same-address-producing-2-different-values – M.M Dec 02 '14 at 20:40
  • @pmr yes, the const bit does make what I said not really applicable. For primitive types though, placement new is a good practice, but ultimately unnecessary, as primitive types are trivially constructed/destructed. See: http://stackoverflow.com/questions/12612488/aliasing-t-with-char-is-allowed-is-it-also-allowed-the-other-way-around/12615861#12615861 – Red Alert Dec 02 '14 at 20:46

3 Answers3

6

Your C style cast is removing the constness, making the assignment possible. After that you write to a value declared const. This invokes undefined behavior and afterwards everything goes. This also means that there is no way to explain the output your are seeing. Most likely the compiler assumed the value never changes and just used constant folding, hence you get x=5, but we will never know for sure.

The take-away: C-style casts are evil and almost never needed.

pmr
  • 58,701
  • 10
  • 113
  • 156
  • 1
    I agree that C-style casts are evil. But you could get the same undefined behavior using `const_cast`. At least it sticks out more. – Fred Larson Dec 02 '14 at 20:21
  • Okay i see now. So the page table just "assumes" that the value of x will be 5 "always". In any case i would never try this ever again i though this was kind of a hack. But i suppose my doubt is cleared . Thanks! – SeasonalShot Dec 02 '14 at 20:24
  • @FredLarson "stick out more" as in "huge red warning sign with the letters SOMETHING STUPID IS ABOUT TO HAPPEN"? Yes, it does. – pmr Dec 02 '14 at 20:39
3

Official answer (according to the C++ language standard):

Undefined behavior.

Practical answer (depending on compiler implementation):

With a global const int x=5, the variable is allocated in the RO-data section of the executable image.

The result of executing *ptr=11 will therefore be an illegal memory access exception during runtime.

With a local const int x=5, the variable is allocated on the (RW) stack section of the executable image.

But since x is constant, the compiler replaces every r-value reference of this variable with the value of 5.

barak manos
  • 29,648
  • 10
  • 62
  • 114
1

"const" tells the compiler, if anyone writes code that tries to modify this object/variable then throw a compile error to prevent them from doing so, and by the way you are free to do any optimization assuming that the value did not change in this context. A C style cast / const_cast says, I know what I am doing, don't bother throwing errors at me as I am going to do it anyway. So by doing both you are living dangerously. Sometimes your get away with it, sometimes the system gets you. Whether variables placed in .rodata cause exceptions when you try to write is platform dependent. If you do not have hardware memory protection and all your code runs from RAM, then you can pretty much write where you want, including overwrite code (.text). For me the beauty of const is that it is infectious (others have called it evil or messy just because of this ).

rakeshdn
  • 135
  • 1
  • 7