3

重複の可能性:
非 const ポインターによる const の変更

最初に以下のコードを見てみましょう。非常に短いコードです。

int main()
{
    const int n=9;
    int *p=(int*)&n;
    *p=5;
    cout<<*p<<endl; //result is 5
    cout<<n<<endl;  // 9
    int a=n+1;
    cout<<a<<endl;  // 10
}

驚いたことに、コンパイラはまったく文句を言いません。結果は、コメントとして示したとおりです。
しかし、それが多かれ少なかれ理にかなっているとすれば、さらに驚くべきことは、それをデバッグすると、n の値が実際に 5 に変更されていることがわかるということです!
しかし、その後、「n」を使用すると、「n」はまだ元の値 9 として扱われるようでした。
それで、コンパイラは「n」の元の値を別の場所に保存したと思いますよね?では、「n」の元の値である 9 は、現在どこに格納されているのでしょうか。
ご協力ありがとうございました!

4

1 に答える 1

3

これはおそらく最適化によるものです。を宣言しconst int n=9ているので、基本的には変更しないことを約束していますn。したがって、コンパイラはcout << n << endl;単純な .xml に自由に最適化できcout << 9 << endl;ます。古い値が他の場所に保存されているとは思いません。

それにもかかわらず、これは未定義の動作です。

デバッグ ビルドであっても、この動作の原因が最適化であることを確認できます。

    cout<<n<<endl;  
01151426  mov         esi,esp  
01151428  mov         eax,dword ptr [__imp_std::endl (11582B4h)]  
0115142D  push        eax  
0115142E  mov         edi,esp  

//HERE:
//
01151430  push        9  
//
//

01151432  mov         ecx,dword ptr [__imp_std::cout (11582B0h)]  
01151438  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (11582ACh)]  
0115143E  cmp         edi,esp  
01151440  call        @ILT+325(__RTC_CheckEsp) (115114Ah)  
01151445  mov         ecx,eax  
01151447  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (11582A8h)]  
0115144D  cmp         esi,esp  
0115144F  call        @ILT+325(__RTC_CheckEsp) (115114Ah)  

n議論にもなりません。

そうnでないconst場合、最適化は不正になります。

00D51426  mov         esi,esp  
00D51428  mov         eax,dword ptr [__imp_std::endl (0D582B4h)]  
00D5142D  push        eax  
00D5142E  mov         edi,esp  

//HERE
//
00D51430  mov         ecx,dword ptr [n]  
00D51433  push        ecx  
//
//

00D51434  mov         ecx,dword ptr [__imp_std::cout (0D582B0h)]  
00D5143A  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0D582ACh)]  
00D51440  cmp         edi,esp  
00D51442  call        @ILT+325(__RTC_CheckEsp) (0D5114Ah)  
00D51447  mov         ecx,eax  
00D51449  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0D582A8h)]  
00D5144F  cmp         esi,esp  
00D51451  call        @ILT+325(__RTC_CheckEsp) (0D5114Ah)  

ここで、 の値は でnはないため、引数スタックにプッシュされますconst

于 2012-07-25T01:55:03.510 に答える