7

Consider this :

#include <iostream>
using namespace std;

int main(void)
{
    const int a1 = 40;
    const int* b1 = &a1;
    char* c1 = (char *)(b1);
    *c1 = 'A';
    int *t = (int*)c1;


    cout << a1 << " " << *t << endl;
    cout << &a1 << " " << t << endl; 

    return 0;
}

The output for this is :

40 65 
0xbfacbe8c 0xbfacbe8c

This almost seems impossible to me unless compiler is making optimizations. How ?

M.M
  • 138,810
  • 21
  • 208
  • 365
shrinidhisondur
  • 771
  • 1
  • 8
  • 18
  • 1
    If your question has been answered, please [mark the answer that you feel best addressed your question as accepted](http://stackoverflow.com/help/someone-answers), rather than posting a comment thanking the answerer. You can also [upvote](http://stackoverflow.com/help/why-vote) the accepted answer and any other answers you found useful. – Adi Inbar Jul 10 '14 at 15:44

4 Answers4

14

This is undefined behavior, you are modifying a const variable so you can have no expectation as to the results. We can see this by going to the draft C++ standard section 7.1.6.1 The cv-qualifiers paragraph 4 which says:

[...]any attempt to modify a const object during its lifetime (3.8) results in undefined behavior.

and even provides an example:

const int* ciq = new const int (3); // initialized as required
int* iq = const_cast<int*>(ciq); // cast required
*iq = 4; // undefined: modifies a const object

In the standard definition of undefined behaviour in section 1.3.24, gives the following possible behaviors:

[...] Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message). [...]

David Xu
  • 5,555
  • 3
  • 28
  • 50
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • Why does modifying a const variable result in undefined behavior? – Ben Mar 26 '14 at 09:42
  • @Ben Because the spec says so. – Bart van Nierop Mar 26 '14 at 09:43
  • 1
    @Ben As Bart says, because the standard says so. The reason the standard says so is 1) to allow the compiler to put the variable in read only memory (you're attempt to modify it could cause the program to crash, for example), and 2) to allow the compiler to propagate the constant value as a constant expression: if you later write `char arr[a1];`, how big do you expect the array to be? – James Kanze Mar 26 '14 at 09:48
  • @ben to add to James excellent comment, the compiler can do some optimization with constant variables as well which would not be available if you were allowed to modify them using tricks. – Shafik Yaghmour Mar 26 '14 at 09:59
  • 1
    @ben a constant should be constant, if it changes it should not be a constant. So trying to do so, is semantically a nonsense. What would happens if someone change the value of PI in the middle of a run ? Nonsense, undefined behaviour. C++ lets you make very dangerous things (this is one of the power of C++), but alas dangerous sometimes leads to nonsense. – Jean-Baptiste Yunès May 24 '14 at 09:19
4

Your code has undefined behaviour, because you are modifying a constant object. Anything could happen, nothing is impossible.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
2

When you qualify them variables const the compiler can assume a few things and generate code, this works fine providing you respect that agreement and not break it. When you've broken it, you'll get undefined behaviour.

Note that when const is removed, it works as expected; here's a live example.

legends2k
  • 31,634
  • 25
  • 118
  • 222
0

As has been explained by others, modifying a const value results in undefined behavior and nothing more needs to be said - any result is possible, including complete nonsense or a crash.

If you're curious as to how this particular result came about, it's almost certainly due to optimization. Since you defined a to be const, the compiler is free to substitute the value 40 that you assigned to it whenever it wants; after all, its value can't change, right? This is useful when you're using a to define the size of an array for example. Even in gcc, which has an extension for variable-sized arrays, it's simpler for the compiler to allocate a constant-size array. Once the optimization exists it's probably applied consistently.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622