1

重複の可能性:
非constポインターを介してconstを変更する

私はC++を勉強していて、ポインターについて非常に興味深いです。そして、私は次のように定数値の値を変更しようとしました(私の先生はそれを呼んでいますbackdoor、私が間違っているかどうかを明確にしてください):

const int i = 0;

const int* pi = &i;

int hackingAddress = (int)pi;
int *hackingPointer = (int*)pi;

*hackingPointer = 1;

cout << "Address:\t" << &i << "\t" << hackingPointer << endl;
cout << "Value:  \t" << i << "\t\t" << *hackingPointer << endl;

system("PAUSE");

return 0;

しかし、結果は非常に奇妙です。2つのアドレスは同じですが、値は異なります。

私のコードはどのように実行されますか?そして、値はどこに0正確1に保存されていますか?

4

3 に答える 3

11

C++開発者が未定義動作と呼ぶ小さなことを発見しました。i「は値0の定数です」とコンパイラーに指示しました。したがって、コンパイラに値を要求すると、i0であることがわかります。

定数の値を変更しようとすると、コンパイラーが行った仮定(定数は定数になる)に違反するため、コンパイラーは無効または一貫性のないコードを生成します。

C ++には、コンパイラがエラーとしてキャッチせずに何かを実行できる状況がたくさんありますが、結果は未定義です。そしてそれを行うと、あなたはあなたが見ているような結果を得ることができます。コンパイラは奇妙で予期しないことをします。

ああ、そしてあなたの先生がこのような例からあなたに何かを教えようとしているなら、彼は間違っています、そしてあなたは非常に怖いはずです。

このようなコードから得られる唯一の保証は次のとおりです。

コンパイラは文字通り好きなことを何でもできます

コードを書くときは、コンパイラと暗黙の契約があります。

「明確に定義されたC++コードを作成すると、C++標準で説明されているのと同じ効果を持つ実行可能ファイルに変換されます」。

このようなことをすると、契約に違反します。そして、コンパイラもそれに従う義務はありません。C ++標準に従って明確に定義されていないコンパイラコードを指定した場合、C ++標準で指定されているとおりに実行可能ファイルを作成することはできず、作成する予定もありません。

于 2012-05-29T10:47:53.183 に答える
2

コンパイラが最適化したようです(int const valueをインライン化)

cout << "Value:  \t" << i << "\t\t" << *hackingPointer << endl;

cout << "Value:  \t" << 0 << "\t\t" << *(0x0044ff28) << endl;

とにかく、あなたはまだ保存されているメモリの値を変更することに成功していますi。しかし、家でこれを試さないでください:-)

于 2012-05-29T10:53:46.087 に答える
0

定数の値を変更することは許可されていません。実際、これは未定義の動作であるため、プログラムは結果として何でも実行できます。

この例では、値が固定されていることがわかっているため、コンパイラはコンパイル時に読み取りを最適化したように見えます。多くの実装は、変更しようとするとクラッシュする可能性がありますが、未定義の動作の結果に賭けたり、信頼したりすることはできません

于 2012-05-29T10:49:18.853 に答える