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印刷時にメモリを実際に見ないように最適化されました(あなたはそれが. それで実際に変わったのは...aaconst

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

于 2013-04-24T13:55:40.147 に答える
3

問題のコードで未定義の動作を呼び出していますconst。constness をキャストすることによって宣言された変数を変更しようとすると、許可されません ( const 変数が実際に ではない変数への参照でない限りconst)。

あなたの結果に対するもっともらしい、そして非常に可能性の高い説明は、コンパイラが の値がa変更されるべきではないことaを知っているということ5です。すなわち。「ルックアップ」は最適化されています。

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)10movl $10, %edi

先に述べたように; コンパイラは、 の値が変化しないと想定し、が使用されるaたびにメモリ位置を読み取る代わりに、a代わりにそれを定数値に置き換えます10

于 2013-04-24T13:56:48.640 に答える