文字列リテラルで初期化された「char *s」に書き込むとセグメンテーション違反が発生するのに、「char s[]」には発生しないのはなぜですか? 質問する

文字列リテラルで初期化された「char *s」に書き込むとセグメンテーション違反が発生するのに、「char s[]」には発生しないのはなぜですか? 質問する

次のコードは 2 行目でセグメント エラーを受け取ります。

char *str = "string";
str[0] = 'z';  // could be also written as *str = 'z'
printf("%s\n", str);

これは完璧に機能しますが、

char str[] = "string";
str[0] = 'z';
printf("%s\n", str);

MSVC および GCC でテスト済み。

ベストアンサー1

C FAQを参照してください。質問1.32

Q : これらの初期化の違いは何ですか?
char a[] = "string literal";
char *p = "string literal";
に新しい値を割り当てようとするとプログラムがクラッシュしますp[i]

A : 文字列リテラル (C ソース内の二重引用符で囲まれた文字列の正式な用語) は、わずかに異なる 2 つの方法で使用できます。

  1. の宣言のように、char の配列の初期化子として、char a[]その配列内の文字の初期値 (および必要に応じてそのサイズ) を指定します。
  2. その他の場所では、名前のない静的な文字配列になり、この名前のない配列は読み取り専用メモリに格納される可能性があり、したがって必ずしも変更できるとは限りません。式のコンテキストでは、配列は通常どおりすぐにポインタに変換されるため (セクション 6 を参照)、2 番目の宣言では p を名前のない配列の最初の要素を指すように初期化します。

一部のコンパイラには、文字列リテラルが書き込み可能かどうかを制御するスイッチがあります (古いコードをコンパイルするため)。また、一部のコンパイラには、文字列リテラルを正式に const char の配列として扱うオプションがあります (エラーをより適切にキャッチするため)。

おすすめ記事