次のプログラムがあります。
char *s = "abcdf";
char s1[50] = "abcdf";
s1[0] = 'Q'; // Line 1
s[0] = 'P'; // Line 2
なぜLine 1
正しく動作しLine 2
、プログラムがクラッシュしたのですか?
次のプログラムがあります。
char *s = "abcdf";
char s1[50] = "abcdf";
s1[0] = 'Q'; // Line 1
s[0] = 'P'; // Line 2
なぜLine 1
正しく動作しLine 2
、プログラムがクラッシュしたのですか?
行 2 は、読み取り専用の実行可能ファイルのデータ セクションを指しますが、行 1 では、プログラムs1
は指定された文字列で配列を初期化します。これはスタックに保存され、変更できます。
char *s = "abcdf";
char s1[50] = "abcdf";
s1[0] = 'Q'; // Line 1
s[0] = 'P'; // Line 2
これは、その定義をプログラムスコープs
に置くか関数内に置くかに応じて、グローバル変数またはローカルスタック変数になることが保証された変更可能なポインターです。使用を開始する前に、コンパイラはテキスト「abcdf」のアドレスs
をにロードするように調整する必要があります。通常、最新のオペレーティングシステムでは、「abcdf」自体は読み取り専用メモリの領域にあり、実行の準備としてプログラムファイルをメモリに読み込む「ローダー」は、CPU自体に読み取り操作を許可するが書き込み操作は許可しないように指示します。つまりs
、変更可能ですが、そうではない「abcdf」を指します。
s1
50文字の変更可能な配列が保証されています。使用を開始する前に、コンパイラはテキスト「abcdf」をその変更可能なバッファにコピーするように調整する必要があります。その後、と同じようにそのバッファを安全に変更できますs1[0] = 'Q'
。
s[0] = 'P'
ポインタs
を使用して、読み取り専用メモリ内の元の変更不可能/定数テキスト「abcdf」を検索し、それを変更しようとします。上記のように、CPUは通常、CPU例外/トラップ/信号/割り込みを生成することによって反応するように構成されています(用語はメーカーによって異なります)。プログラムは失敗します。