1

我在 c++ 中编写了以下代码。
我想对 const 变量进行强制转换并对其进行更改,这是代码:

#include <iostream>
using namespace std;
int main()
{
    int const a = 5;
    int* ptr = (int*)&a;
    *ptr = 10;
    cout<<"a is : "<< a << endl;

    system("pause");
}

这段代码通过了编译器,我希望程序打印屏幕 10 ,
但屏幕上的结果是 5。
当我运行调试器时, &a 中的内存已更改为 10,就像我预期的那样。
知道为什么吗?

4

2 回答 2

3

首先,这是未定义的行为。不要这样做。其次,编译器优化了实际上在&a您打印时查看内存,a因为您告诉编译器a永远不会改变(您说它是const)。所以它实际上变成了...

cout << "a is : "<<5 << endl;

于 2013-04-24T13:55:40.147 回答
3

您正在使用有问题的代码调用未定义的行为,试图更改声明为的变量,方法const是丢弃 const 是不允许的(除非const 变量实际上是对不是的变量的引用const)。

对您的结果的一种合理且极有可能的解释是,编译器知道 的值不a应该改变,因此它几乎可以替换所有出现的awith 5。IE。“查找”已优化。

当它被声明为 always be 时,为什么要查看它的地址a来读取它的值5


让我们看看编译器可能会将代码片段转换成哪些指令

foo.cpp

void func (int)
{
  /* ... */
}

int
main (int argc, char *argv[])
{
  const int a = 10; 

  int * p     = &const_cast<int&> (a);

  *p = 20; 

  func (a);
}

main如给出的组装说明g++ -S foo.cpp

main:
.LFB1:
  .cfi_startproc
  pushq %rbp
  .cfi_def_cfa_offset 16
  .cfi_offset 6, -16 
  movq  %rsp, %rbp
  .cfi_def_cfa_register 6
  subq  $32, %rsp
  movl  %edi, -20(%rbp)
  movq  %rsi, -32(%rbp)
  movl  $10, -12(%rbp)
  leaq  -12(%rbp), %rax
  movq  %rax, -8(%rbp)
  movq  -8(%rbp), %rax # store the adress of `a` in %rax
  movl  $20, (%rax)    # store 20 at the location pointed to by %rax  (ie. &a)
  movl  $10, %edi      # put 10 in register %edi (placeholder for first argument to function)
                       # # notice how the value is not read from `a`
                       # # but is a constant
  call  _Z4funci       # call `func`
  movl  $0, %eax
  leave
  .cfi_def_cfa 7, 8
  ret 
  .cfi_endproc

如上所见, 的值20确实放置在包含 ( ) 的地址的存储%rax地址(%rax)amovl $20, (%rax)但我们调用的参数void func (int)是常数10( movl $10, %edi)。

如前所述;编译器假定 的值a不会改变,而不是每次a使用时都读取内存位置,而是将其替换为常量 value 10

于 2013-04-24T13:56:48.640 回答