メモリが読み取り専用である以下のプログラムがありますが、それでも書き込み可能です。
main()
{
char *p="amit";
p[0]="s";
printf("%s",p);
}
出力は「smit」です
p
読み取り専用の場所を指しているため、期待される出力ですか? このプログラムを GCC または Visual C++ で実行すると、セグメンテーション エラーが発生しますが、Turbo C++ では "smit" が発生します。
この動作を確認してください...
未定義の動作は未定義の動作です。何を得ても、文句を言うことはできません。
文字列リテラルは、以前は書き込み可能なメモリにありました。古いコンパイラにはこの動作があります。一部のコンパイラ (少なくとも古いバージョンの gcc、4.X バージョンでは削除されているようです) には、それを取得するオプションがあります。それに依存する古いアプリケーションを移植するのを助けることを除いて、それを使用しないことをお勧めします。
文字列リテラルに書き込むと未定義の動作が発生するため、コンパイラはそれを行うときに必要なことを何でも実行できます。
簡単な答えは、Turbo C++ はリアルモード用にコンパイルされるため、メモリは保護されないということです。コンパイラもOSも、どこにでも何かを書くのを止めません。
文字列が使用するメモリは、読み取り専用である必要"amit"
はありません。実際、これはコンパイラに依存しているため、この現象が発生しています。
問題は、スタック上でポインターを宣言したことですが、「amit」がどこに格納されることになっているのか明確ではありません。スタックにも文字列が必要ですが、これを行う最も簡単な方法は、p をポインターから文字配列に変更して、そのストレージを割り当てることです。
コードを次のように変更します。
main()
{
char p[] = "amit";
p[0]='s';
printf("%s",p);
}
ランタイム マシンのメモリが読み取り専用であることは、まったく関係ありません。p を介してメモリに間接的に書き込もうとする前に (これは読み取り/書き込みであると想定しています)、まずそのメモリを定義する必要があります。もちろん、ランタイム メモリが実際に読み取り専用である場合は、コンパイル エラーをいくつ修正しても機能しません。
だからあなたは持っているかもしれません:
main()
{
char amit[20] = "amit";
char *p = amit; // which is the same as &amit[0]
// yes, you are permitted to write into amit[] like these next two lines:
p[0]="s";
p[1] = '\0'; // you must terminate the string if you don't want to use strcpy( ) or its friends
// but it's better in every way to strcpy( ) into amit[], like this:
strcpy( amit, "s" );
printf("%s",p);
}
「amit」に使用されるメモリは読み取り可能であるだけでなく、これはコンパイラに依存する天気であり、場所 p[0] で書き換えることができます。(GCC) 4.1.2 でも同じことを観察しました。はい、期待される出力とその未定義の動作 ...