-4

Not a Duplicate. Please read Full question.

#include<iostream>
using namespace std;

int main()
{
    const int a = 5;
    const int *ptr1 = &a;
    int *ptr = (int *)ptr1;
    *ptr = 10;
    cout<<ptr<<" = "<<*ptr<<endl;
    cout<<ptr1<<" = "<<*ptr1<<endl;
    cout<<&a<<" = "<<a;
    return 0;
}

Output:

0x7ffe13455fb4 = 10
0x7ffe13455fb4 = 10
0x7ffe13455fb4 = 5

How is this possible?

SergeyA
  • 61,605
  • 5
  • 78
  • 137
Sniper
  • 1,428
  • 1
  • 12
  • 28

3 Answers3

2

You shouldn't rely on undefined behaviour. Look what the compiler does with your code, particularly the last part:

    cout<<&a<<" = "<<a;
  b6:   48 8d 45 ac             lea    -0x54(%rbp),%rax
  ba:   48 89 c2                mov    %rax,%rdx
  bd:   48 8b 0d 00 00 00 00    mov    0x0(%rip),%rcx        # c4 <main+0xc4>
  c4:   e8 00 00 00 00          callq  c9 <main+0xc9>
  c9:   48 8d 15 00 00 00 00    lea    0x0(%rip),%rdx        # d0 <main+0xd0>
  d0:   48 89 c1                mov    %rax,%rcx
  d3:   e8 00 00 00 00          callq  d8 <main+0xd8>
  d8:   ba 05 00 00 00          mov    $0x5,%edx   <=== direct insert of 5 in the register to display 5
  dd:   48 89 c1                mov    %rax,%rcx
  e0:   e8 00 00 00 00          callq  e5 <main+0xe5>
    return 0;
  e5:   b8 00 00 00 00          mov    $0x0,%eax
  ea:   90                      nop
  eb:   48 83 c4 48             add    $0x48,%rsp
  ef:   5b                      pop    %rbx
  f0:   5d                      pop    %rbp
  f1:   c3                      retq

When the compiler sees a constant expression, it can decide (implementation-dependent) to replace it with the actual value.

In that particular case, g++ did that without even -O1 option!

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
1

When you invoke undefined behavior anything is possible.

In this case, you are casting the constness away with this line:

int *ptr = (int *)ptr1;

And you're lucky enough that there is an address on the stack to be changed, that explains why the first two prints output a 10.

The third print outputs a 5 because the compiler optimized it by hardcoding a 5 making the assumption that a wouldn't be changed.

imreal
  • 10,178
  • 2
  • 32
  • 48
0

It is certainly undefined behavior, but I am strong proponent of understanding symptoms of undefined behavior for the benefit of spotting one. The results observed can be explained in following manner:

const int a = 5

defined integer constant. Compiler now assumes that value will never be modified for the duration of the whole function, so when it sees

cout<<&a<<" = "<<a;

it doesn't generate the code to reload the current value of a, instead it just uses the number it was initialized with - it is much faster, than loading from memory.

This is a very common optimization technique - when a certain condition can only happen when the program exhibits undefined behavior, optimizers assume that condition never happens.

SergeyA
  • 61,605
  • 5
  • 78
  • 137