Change constant value [duplicate]

泄露秘密 提交于 2019-12-13 11:26:58

问题


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?


回答1:


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.




回答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!




回答3:


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.



来源:https://stackoverflow.com/questions/39106137/change-constant-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!