0

ここに私のテストコードがあります:

#define print(A) cout << #A <<  " = " << A <<  endl;
int main()
{
    const int e = 2;
    int *p = (int *)&e;
    *p = 4;

    print(e);
    print(*p);
    print(&e);
    print(p);
}

結果:

e = 2;
*p = 4;
&e = 0xbfc6b458;
p = 0xbfc6b458;

"p" は同じアドレスに従って "e" を指しているため、*p と "e" はどのように異なるのでしょうか? これは危険ですよね?

4

6 に答える 6

8

キャストアウェイconstは合法です。このようにして取得したポインター (または参照) を使用して、constオブジェクトを変更する (しようとする) ことは違法です。

あなたのコードは未定義の動作をもたらします。何でもできるし、意味を成す必要もない。

于 2012-08-20T11:12:07.697 に答える
3

何らかの方法で定数変数を変更すると、未定義の動作が発生します。
そうです、これは危険です。
未定義の動作とは、任意の動作が可能であり、有効な動作を期待できないことを意味します。コンパイラは自由に結果を出すことができ、標準ではそうすることが許可されています。UB が呼び出されると、そのプログラムは有効なプログラムではなくなります。そのため、UB を引き起こすコードは避けるのが最善です。

于 2012-08-20T11:12:29.370 に答える
1

「e」は定数であるため、それらは異なる場合があります。したがって、適切なコンパイラーは、メモリから読み取るのではなく、コンパイル時に値をプラグインします。

アドレスを取得しているため、「実際の」変数はまだありますが、実際には使用されていません。

そして、値をまったく変更できたのは「幸運」です。「const」と宣言されているため、コンパイラはそれを読み取り専用メモリに配置できた可能性があります。

いずれにせよ、const 値を変更すると、「未定義の動作」が発生します。幸運なことに、あなたは愚かなゲームで世界を破壊しませんでした。

于 2012-08-20T11:13:04.910 に答える
0

未定義の動作である定数変数に書き込もうとしています(はい、名前はかなり矛盾していますが、余談です)。

于 2012-08-20T11:13:13.203 に答える
0

const をキャストしています。これは未定義の動作である間違った値を与えています。どちらかである必要があります

int e = 2;
int* p = (int *)&e;
*p = 4;

また

const int e = 2;
const int* p = (const int *)&e;
*p = 4;

後者は、constに書き込んでいるため、コンパイルエラーが発生します。

于 2012-08-20T11:15:01.890 に答える
0

変数を定義:

 const int e = 2;

ディレクティブ const tell c/c++ compiler check if the L-value of e variable. コンパイラは、コードが e に新しい値を割り当てるのを防ぎます。

int* p = (int *)&e;

p はポインタ (これも int 4 バイト) であり、任意の値を割り当てることができます p = (((int *) e ) -2)+2. コンパイラは、*p が定数かどうかをチェックする必要はありません。それは c/c++ 言語の柔軟性だと思います。より良い方法はポインターを避けることです。

于 2012-08-20T13:30:46.553 に答える