Question

When I write this code fragment, after modifying the value of const variable i through pointer I am getting value of i as 10, but when i print *ptr i get 110.

const int i = 10;
int *ptr = const_cast<int *>(&i);
*ptr = *ptr + 100;
cout << "i:     " << i << "\t*ptr:      " << *ptr << endl;

I am getting output i: 10 and *ptr :110.

And in this case I am having a const variable x as a member variable of class Base. And through function show() I am able to modify the value of const variable x i.e when I print x and *ptr I get changed value in both.

class Base
{
public:
const int x;
Base(int i) : x(i) {}
virtual void show()
{
            int *ptr = const_cast<int *>(&x);        
            int *ptr = const_cast<int *>(&x);
            cout << "In Base show:\n";
            cout << "Address of x   :       " << &x << endl;
            cout << "Address in ptr :       " << ptr << endl;
            cout << "value in x     :       " << x << endl;
            cout << "value in ptr   :       " << *ptr << endl;
            *ptr = *ptr + 10;
            cout << "After modifying        " << endl;
            cout << "value in x     :       " << x << endl;
            cout << "value in ptr   :       " << *ptr << endl;
    }
};

class Derived : public Base
{
    public:
    Derived(int i) : Base(i){}
    virtual void show()
    {
            int *ptr = const_cast<int *>(&x);
            cout << "In Derived show:\n";
            cout << "Address of x   :       " << &x << endl;
            cout << "Address in ptr :       " << ptr << endl;
            cout << "value in x     :       " << x << endl;
            cout << "value in ptr   :       " << *ptr << endl;
            *ptr = *ptr + 10;
            cout << "After modifying        " << endl;
            cout << "value in x     :       " << x << endl;
            cout << "value in ptr   :       " << *ptr << endl;
    }
};
int main()
{
    Base bobj(5),*bp;
    Derived dobj(20), *dptr;
    bp = &bobj;
    bp->show();
    bp = &dobj;
    bp->show();
    return 0;
}


The output which I am getting is this 
In Base show:
Address of x    :   0x7fff82697588
Address in ptr  :   0x7fff82697588
value in x          :   5
value in ptr    :   5
After modifying 
value in x          :   15
value in ptr    :   15

In Derived show:
Address of x        :       0x7fff82697578
Address in ptr      :   0x7fff82697578
value in x          :       20
value in ptr        :       20
After modifying 
value in x          :       30
value in ptr        :       30

Can anybody help.

Was it helpful?

Solution 2

The reason is that your compiler has inlined the value of i into the code when compiling this line:

cout << "i: " << i << "\t*ptr: " << *ptr << endl;

Because i is a const variable, the compiler has optimised the code by replacing i in the above line with 10. If we look at the generated assembly (I'm using VS2010):

002314F2  mov         ecx,dword ptr [ptr]  // ptr is being pushed here (110)
002314F5  mov         edx,dword ptr [ecx]  
002314F7  push        edx  
002314F8  push        offset string "\t*ptr:      " (23783Ch)     
002314FD  mov         ebx,esp  
002314FF  push        0Ah  //  0Ah is being pushed here (A is hex for 10)
00231501  push        offset string "i:     " (237830h) 

What has happened is that you have modified the constant in memory, but the generated assembly doesn't actually use the memory address - it simply outputs '10' regardless of what's in memory.

As said by Kerrek, this is undefined behavior, so other compilers may do something completely different to this.

In general it is a bad idea to use const_cast with few exceptions.

OTHER TIPS

Your code simply has undefined behaviour: You must not modify a constant object, and your const_cast allows you to violate that (which is why it's basically never a good idea to use const_cast, with very few and very rare exceptions). So there's little purpose in asking about the whys and hows of the particular way your code breaks. But if you must know, constant integral expressions are often folded by value right into the places where they're referred to, which looks like what's happening in your case.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top