3

Possible Duplicate:
C/C++ changing the value of a const

The following program:

int main()
{
    const int x = 10;
    int * p = (int *)&x;
    *p = 12;
    cout<<x<<endl;
    cout<<*p<<endl;
    return 0;
}

Gives an output of:

10
12

What is the effect of casting &x to (int *) and why is the value of x still 10 ? I expected it to be 12.

Another doubt

Why cant we cast say int ** to int const ** ? Rather this operation is valid

void f(int const ** p);
void g(int const * const * p);

int main()
{
    int ** p = /*....*/
    f(p);   //Error
    g(p);   //OK
}

Please help me understanding this with suitable example Thanks !!!

Community
  • 1
  • 1
Kundan Kumar
  • 1,974
  • 7
  • 32
  • 54
  • 3
    The 10 may be due to optimization; the compiler knows that x is const so it invokes `cout << 10 << endl;` instead of `cout << x << endl;`. What's less clear is whether the compiler optimizes the second output to `cout << 12 << endl;`. – Jonathan Leffler May 11 '12 at 15:01
  • @JonathanLeffler....but what about the pointer p ? It was pointing to the address of x ...I dont know what exactly is happening after casting ((int*)&x step)...the pointer should modify the value of x normally...please explain whats going on in the memory address of 'x' here – Kundan Kumar May 11 '12 at 15:04
  • What happens after the `int *p = (int *)&x;` step is undefined behaviour. Anything can happen; what happens is OK. Don't do it. – Jonathan Leffler May 11 '12 at 15:07
  • I've removed the "C" tag since C++ and C are not the same language, particularly in the context of this question. – tinman May 11 '12 at 15:08
  • @JonathanLeffler...please see the second part of my question – Kundan Kumar May 11 '12 at 15:13

4 Answers4

8

You are invoking undefined behaviour by modifying a variable declared as const. Any result whatsoever is legitimate output from the program, though some results are more plausible than others.

As I noted in a comment:

The 10 may be due to optimization; the compiler knows that x is const so it may invoke:

cout << 10 << endl;

instead of:

cout << x << endl;

What's less clear is whether the compiler optimizes the second output to:

cout << 12 << endl;

You'd have to look at the assembler generated to know for sure. But since the whole program is invoking undefined behaviour, the compiler is correct, regardless of what it does.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
2

The compiler will substitute a literal value when it is assigned to a const int. Effectively your program looks like:

        cout<<10<<endl;
        cout<<*p<<endl;
Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • The compiler *will* do nothing of the sort. It *might*. It's undefined behavior. – Edward Strange May 11 '12 at 15:08
  • @CrazyEddie, the part of the program that casts away constness will definitely produce undefined behavior, but I wasn't addressing that part since it appears to be doing something sensible. A `const int` is a compile-time constant as defined by the standard. – Mark Ransom May 11 '12 at 15:16
  • Again that's wrong. There's nothing wrong with casting away constness; UB comes when you write to the result. Also `const int` is not a compile-time constant, it can be used in constructs requiring one (which the OP is not doing) and only when various other requirements are met. HUGE difference. – Edward Strange May 11 '12 at 15:41
1

As of the main question, it has already been answered: modifying a constant object is undefined behavior.

For the second question, consider that if it was allowed you could break const-correctness inadvertidly:

const int k = 10;
void f(int const ** p) {
    *p = &k;                   // Valid, p promises not to change k
}
void g(int const * const * p);

int main()
{
    int *p;
    int ** pp = &p;
    f(pp);                     // If allowed: p points to k!!!
    p = 5;                     // Modifying a constant object!!!
    g(pp);                     //OK
}

In the case of g, because the signature of the function promises that the intermediate pointer will not be changed, the compiler knows that g will not modify *pp, which means that it cannot make *pp (i.e. p) point to a constant object, and const-correctness is guaranteed.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
0

well, it is interesting question. when you remove the const prefix of x you will get the result as you wish.

int main()       
{               
 int x = 10;               
 int * p = (int *)&x;               
 *p = 12;              
 cout<<x<<endl;              
 cout<<*p<<endl;               
 return 0;      
}

I think it is the const mark prevent the change of the value of x.

Mike
  • 59
  • 3