0

重複の可能性:
単純なCコードがセグメンテーション違反を受け取るのはなぜですか?

コードスニペット2がスニペット1のように動作しないのはなぜですか?

//Code snippet 1
char pstr[] = "helloworld";
char *p = pstr; 
p[2] = 'd';

//Code snippet 2
char *p = "helloworld";
p[2] = 'd'; //error: access violation

PS私の無知を許してください。

4

4 に答える 4

3

最初のスニペットはcharの配列を作成し、その内容を「helloworld」に初期化します。次に、3番目の要素を変更します。

2つ目は、文字列リテラルを指すcharへのポインタを作成するだけです。次に、そのリテラルの3番目の文字を変更しようとします。文字列リテラルは、多くの最新のコンパイラによって生成されたコードでは書き込みできません。

編集:

GCCには、-fwritable-strings文字列リテラルを書き込み可能にするオプションがありました。これは、この動作に依存するレガシーコードが周りにあるためです。このオプションは、GCC4.0リリースシリーズで削除されました。

于 2010-12-24T00:42:37.387 に答える
2

"helloworld"の配列ですconst char。型システムには、読み取り専用データを指すためにchar*を使用するコードが多数存在し、これが安全であるため、でそれを指すことができる穴があります。char *

ただし、ルールが適用されます。データへの非定数ポインターを作成してもconst_cast、実際にデータに書き込むことはできません。const

于 2010-12-24T00:44:29.977 に答える
0

彼らがどのように異なった振る舞いをしているのかを教えていただければ助かります。

しかし、推測として、あなたの問題は、2番目の形式の「p」が読み取り専用メモリ内の文字列を指していることだと思います。ポインタ'p'を介して書き込もうとすると、プログラムが失敗します。

Gnuc++コンパイラがこれについて警告することをお伝えできます。

于 2010-12-24T00:41:21.940 に答える
0

「のように動作しない」と言うときは、一方が不正なアクセス例外(または同様のもの)をスローし、もう一方がコンパイル時の警告またはエラーを出すことを意味していると思いますか?

答えは、最初のケースでは、自分のメモリへのポインタを作成し、それにc9ontentsをコピーしているということです。その時点で、コンパイラはそれが静的メモリへのポインタであったことを忘れます。ただし、ランタイムシステムは忘れません。

他の場合、コンパイラはpが静的メモリへのポインタであることを「知っている」ので、「おっ、おい、それはできない」と言う機会があります。

しかし、これは、それが何が違うのかを正確に知らなくても、少し推測です。また、コンパイラと実装に依存します。

于 2010-12-24T00:42:49.397 に答える