2016-08-23 13 views
-4

重複しません。完全な質問をお読みください。定数値を変更してください

#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; 
} 

出力:

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

どのようにこれは可能ですか?

+2

*定数の変更は擬似語の一種です。 *未定義の動作につながります*。 –

+2

完全な質問は何ですか?重複していないのはどうですか? – SergeyA

+3

定義されていない動作は、定義により定義されていません。 –

答えて

0

これは確かに未定義の動作ですが、私は未定義の動作の症状を理解することを強く支持しています。観察された結果は、次のように説明することができる。

const int a = 5 

定義された整数定数。コンパイラは現在値が関数全体の期間中に変更されることはありませんと仮定し、それが

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

を見たときには、代わりにそれがちょうど数それを使用して、aの現在の値をリロードするためのコードを生成しません。メモリからロードするよりもはるかに高速です。

これは非常に一般的な最適化手法です。プログラムが未定義の動作を示す場合にのみ特定の条件が発生する可能性がある場合、オプティマイザは条件が発生しないとみなします。

1

未定義の動作を呼び出すと、何かが可能です。

この場合は、この行を離れてconst性をキャストしている:

int *ptr = (int *)ptr1; 

そして、あなたは、なぜ最初の二つのプリントを説明して変更するスタック上のアドレスがあることを十分に幸運10を出力します。

5を出力します。55のハードコーディングで最適化したため、aが変更されないことを前提としています。

2

未定義の動作に頼るべきではありません。コンパイラは、コード、特に最後の部分で何を見て:

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 

コンパイラは定数式を見たとき、それは実際の値に置き換えることを(実装依存)を決めることができます。

この特定のケースでは、g ++は、-O1オプションを使用してもそのようにしました!

関連する問題