1

Both &i(inside main function) and p(inside func function) holds the same address. Well I know that a constant object/variable cannot be modified but I'm able to increment the variable i using (*p)++ in the func function, but the result is not reflecting in the main function. Why is that?

#include <iostream>
using namespace std;

void func(int *p){
    (*p)++;
    printf("%p %d\n", p, *p);
}

int main(int argc, char **argv){
    const int i = 47;
    const int *p = &i;
    func(const_cast<int *>(p));
    printf("%p %d\n", &i, i);
    return 0;
}

I'm getting this output:

000000000022fe44 48
000000000022fe44 47
user3484291
  • 217
  • 2
  • 7
  • 3
    Beware! Here be dragons! – bolov Dec 31 '14 at 14:22
  • You told the compiler `i` is `const`. It folded the constant value in to the printf arg. It's not obligated to be that sensible about it, or sensible at all. You lied to it. It relied on what you told it. – jthill Dec 31 '14 at 15:14

2 Answers2

6

Because of undefined behavior. You are modifying constant data. That const_cast should be a big hint.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
5

Object declared const at point of it's definition is truly a const object. That mean results of modifying that object is undefined.

Undefined means it's totally upto the compiler what it wants to do with your code. In your case, it seems compiler allocated that truly const in read only memory. When you passed this to function taking non-const pointer, compiler might have provided that function with another memory containing similar value. But that's just my speculation.

EDITED in response to comment by @FreeNickName:-

Since addresses of both pointers ( one in main and other in func )are same, I think above is not giving correct/complete picture what's going on under the hood. Maybe compiler is just ignoring that increment instruction as it is being applied on memory that's read only.

ravi
  • 10,994
  • 1
  • 18
  • 36
  • Your explanation seems reasonable, but it's interesting that pointer values in the main function and in the func function are identical, so it's weird that values are different. Anyway, +1) Happy New Year! :) – FreeNickname Dec 31 '14 at 14:31
  • @FreeNickname First same to you...yeah good point I failed to notice that. – ravi Dec 31 '14 at 14:33
  • The compiler couldn't have allocated the constant in R/O memory. If it had, then the statement `(*p)++` would cause access violation. It is simpler than that: every time you use the name of an integral constant as an rvalue (such as in the call to `printf`), the compiler simply replaces with its verbatim value. – ach Dec 31 '14 at 14:47
  • 3
    @FreeNickname `const int i = 47;` is a constant. When the compiler sees this it is allowed to optimize away loading the value _from_ `i` and instead use whatever value you are assigning to it. When you call `printf` in `main` it is doing `printf("%p %d\n", &i, 47)`. When you print the value in `func` it doesn't know it's `const` and loads it from memory. This is why you get two different values. – Captain Obvlious Dec 31 '14 at 14:49
  • I always wanted to say this... Thank you, @CaptainObvlious :) – FreeNickname Dec 31 '14 at 14:51
  • @CaptainObvlious yeah now we have complete picture – ravi Dec 31 '14 at 15:00
  • @CaptainObvlious but why this behavior cause crash sometimes... – ravi Dec 31 '14 at 15:11
  • @ravi The only definitive answer I can give is because of UB. It's possible the value has been placed in read only memory. For instance if you're building with the MS C++ compiler and you change `i` to be `static` the statement `(*p)++;` breaks because `i` gets placed in read only memory. – Captain Obvlious Dec 31 '14 at 15:56