conversion between const to nonconst

Feb 7, 2011 at 9:21pm
Anyone can explain why the second output is 0, rather than 1.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

int main() {
    
    const int x = 0;
    
    int const *py = &x;
    
    int *px = const_cast<int *>(&x);
    
    cout << *px << endl;        // output 0
    
    *px = 1;
    
    cout << x << endl;          // output 0, I don't understand
    cout << *px << endl;        // output 1
    cout << *py << endl;        // output 1
    
    cout << px << endl;         // 0x22ff24
    cout << py << endl;         // 0x22ff24
    
    return 0;
}
Feb 7, 2011 at 9:31pm
Cause what you are doing is illegal.
Feb 7, 2011 at 9:56pm
I understand we should not try to change the value of a constant. In this sense the code above is illegal.

But the code above is allowed by the C++ compiler. I can compile it without any warning or error.

Here I just use it as example to figure out what is the difference between x and *px. thanks,
Feb 7, 2011 at 10:01pm
But the code above is allowed by the C++ compiler. I can compile it without any warning or error.


The compiler will only complain if you have some kind of syntax error. It doesn't catch logic errors.

Here, the logic you're doing (modifying a constant) is undefined, which is why you get weird results.
Feb 7, 2011 at 10:27pm
thanks for your reply.

You mean since this kind of behavior (i.e., changing the value of a constant) is not defined inside the compiler, the consequence of this kind of action could be anything, and there is no way to judge what is "correct" or "incorrect". In this sense, any outcome of x could be said "correct" or "incorrect".

Am I right?
Feb 7, 2011 at 11:47pm
the consequence of this kind of action could be anything


Correct.
Feb 8, 2011 at 2:37pm
Since you declared x as "const", the compiler is allowed to assume that the value of x will not change. That said,
the compiler is free to replace memory accesses of x with the actual value, and in fact, not even allocate memory
for x.

However, as soon as you take the address of a variable, the compiler can no longer optimize it into a register --
it has to allocate memory for it. So you've got two different things going on. First, the compiler optimized the
line cout << x << endl; into cout << 0 << endl;. Second, line 11 caused the compiler
to allocate memory for x so it could take its address. References to x via pointer will now read the memory location.
Hence your two different answers.

Moral to the story: const_cast is very dangerous. In fact, the result of modifying a value which has had its constness
casted away with const_cast is undefined behavior according to the standard. const_cast<> really was only intended
to allow integration with legacy C functions that aren't const correct.
Feb 8, 2011 at 3:48pm
First, the compiler optimized the line cout << x << endl; into cout << 0 << endl;.

Can't you get around that problem by using the keyword volatile?
Last edited on Feb 8, 2011 at 6:54pm
Feb 8, 2011 at 4:39pm
Can't you get around that problem by using the keyword volatile to get around that?


This sounds like a bad, bad idea. How about removing the const keyword from the original declaration if you have to modify it... :P

Feb 8, 2011 at 6:55pm
True, but it was just about the particular 'away-optimizing' problem.
Topic archived. No new replies allowed.