コードにこれに似たものを書きました
const int x=1;
int *ptr;
ptr = &x;
*ptr = 2;
これはすべてのコンパイラで機能しますか? 定数変数を変更していることに GCC コンパイラが気付かないのはなぜですか?
const
実際には「一定」という意味ではありません。Cで「一定」であるものには、コンパイル時に決定される値があります。リテラル42
はその一例です。キーワードはconst
実際には読み取り専用を意味します。たとえば、次のことを考慮してください。
const int r = rand();
の値はr
プログラムの実行時まで決定されませんが、const
キーワードは、r
初期化後に変更することを許可されていないことを意味します。
あなたのコードでは:
const int x=1;
int *ptr;
ptr = &x;
*ptr = 2;
割り当てptr = &x;
は制約違反です。つまり、準拠するコンパイラがそれについて文句を言う必要があります。const int*
(const intへのポインタ)値を非constint*
オブジェクトに合法的に割り当てることはできません。コンパイラが実行可能ファイルを生成する場合(実行する必要はありません。拒否する可能性があります)、動作はC標準で定義されていません。
たとえば、生成されたコードは実際に値2
を-に格納する場合がありますが、コンパイラは初期化後に変更できないことを認識しているためx
、後で参照するとx
値が生成される場合があります。そしてそれはあなたがそう言ったので、として定義することによってそれを知っています。コンパイラに嘘をついた場合、結果は恣意的に悪いものになる可能性があります。1
x
x
const
実際、起こりうる最悪の事態は、プログラムが期待どおりに動作することです。つまり、検出が非常に難しいバグがあるということです。(しかし、あなたが得るべきだった診断は大きな手がかりになります。)
悪いプログラマー。ノームーンパイ!
const を変更する必要がある場合は、const 以外の変数にコピーしてから操作してください。const には理由があります。const を「こっそり」使用しようとすると、実行時に重大な問題が発生する可能性があります。つまり、オプティマイザが値をインラインで使用した可能性があります。
const int x=1;
int non_const_x = x;
non_const_x = 2;
ここでこれについての良い議論があります:邪悪なキャストは邪悪なコンパイラによって打ち負かされますか?
次の理由により、gcc がこれをコンパイルすることを期待します。
ただし、それが機能するかどうかは、コードのコンパイル方法、選択したコンパイル オプションに対する const の実装方法、およびターゲット CPU とアーキテクチャによって異なります。それはうまくいくかもしれません。または、クラッシュする可能性があります。または、「ランダムな」メモリビットに書き込み、奇妙な効果を引き起こす(または引き起こさない)可能性があります。それは良いコーディング戦略ではありませんが、それはあなたの質問ではありません:-)