Saurabh Sharma
Saurabh Sharma

Reputation: 154

Explanation of code snippet containing const_cast

int main() {
  const int i =10;
  int *j = const_cast<int*>(&i);
  cout<<endl<<"address of i "<<&i;
  cout<<endl<<"value of  j "<<j;
  (*j)++;
  cout<<endl<<"value of  *j "<<*j;
  cout<<endl<<"value of i "<<i;
  // If Not use Const //
  int k = 10;
  int *p = &k;
  cout<<endl<<"address of k "<<&i;
  cout<<endl<<"address of p "<<&p;
  (*p)++;
  cout<<endl<<"value of  *p "<<*p;
  cout<<endl<<"value of  k  "<<k<<endl;
}

Output is :

address of i 0xbf8267d0
value of j 0xbf8267d0
value of *j 11
value of i 10
address of k 0xbf8267d0
address of p 0xbf8267c8
value of *p 11
value of k 11

Can someone please explain why at the 3rd and 4th line of output

*j is 11 and i is 10.

Why is i also not 11?

Upvotes: 0

Views: 90

Answers (2)

The explanation is simple: Undefined Behaviour is undefined. When you use const_cast to cast away constness of an object which was actually declared const and then modify it, your program exhibits Undefined Behaviour and it can do literally anything. It can do what you expect, do something you don't expect, it can order pizza online.

In your particular case, the compiler probably optimised all uses of i by replacing it with the literal 10 (because i is const, so its value cannot ever change in any way).

At the same time, i was probably not placed in a read-only part of memory (otherwise, you'd get a crash on (*j)++), and since j is a pointer to int (and not to const int), reading from *j cannot be optimised away and so the value actually stored in *j (which is the storage of i) is printed.

But the above is just speculation, really. The actual reason could be anything. A program with Undefined Behaviour is simply wrong and nothing can be predicted about its behaviour.

Upvotes: 4

Ryan Haining
Ryan Haining

Reputation: 36802

The compiler can assume that a const variable in such a situation won't be modified. It can take steps to generate more efficient code. In your example since i is declared to be const the compiler replaces the std::cout << i with (effectively) std::cout << 10

Casting away the constness results in undefined behavior, so nothing is actually guaranteed to happen.

Consider something similar

const int i = 5;
// ...
if (i > 10) { // impossible!
    std::cout << "hello world!";
}

In the above, an optimizing compiler can, at compile time, figure out that the constant 5 can't possibly be greater than 10, so it will drop the if check and the body, if you looked into the assembly, you wouldn't even see the "hello world!" string because it would have been optimized away and thrown out! Even if you replaced the ... with a const_cast and modified the value of i that doesn't change the optimization that the compiler is allowed to perform assuming i doesn't change.

Upvotes: 6

Related Questions