char *p = "string"; //creates pointer to constant string
char p[] = "string"; //just an array with "string"
なぜ私は最初の例で定数文字列へのポインタを作成するのですか?それは単に "文字列"を持つメモリ内の場所を参照するポインタではないでしょうか?Cのconst文字列へのポインタ
char *p = "string"; //creates pointer to constant string
char p[] = "string"; //just an array with "string"
なぜ私は最初の例で定数文字列へのポインタを作成するのですか?それは単に "文字列"を持つメモリ内の場所を参照するポインタではないでしょうか?Cのconst文字列へのポインタ
残念なことにC(およびC++ 03、互換性については)では合法です。しかし、ポインタを介して文字列リテラルを変更しようとすると、未定義の動作になります。だから、より良い常に最初のケースでconst char*
const char * cp = "Hello"; //OK
char* p = "Hello"; //OK (unfortunately)
cp[0] = 'Y'; //Compile-time error, good
p[0] = 'Y'; //no compiler error, undefined behavior
最初のケースでは、"string"
がプロセスの読み取り専用領域に格納される可能性があります。したがって、p
が指すメモリを変更しようとすると、未定義の動作が発生します。
2番目のケースでは、実際のメモリは実行時に(またはプログラム起動時にローカル変数でない場合はプロセスの適切なセクションで)スタックに割り当てられ、初期化されるため、メモリの変更はOKです。
最初のケースは次のように示すことができる。後者の場合であるのに対し
+---+ +---+---+---+---+---+---+---+
| | ----> | s | t | r | i | n | g | \0|
+---+ +---+---+---+---+---+---+---+
p
:
+---+---+---+---+---+---+---+
| s | t | r | i | n | g | \0|
+---+---+---+---+---+---+---+
p
あなたは、彼らがしていることを聞いたことがあるかもしれないが2つの宣言は、有意差を持っています低品質のCプログラミングブックと同じです。第二のタイプchar []
の配列ある一方
最初は、タイプchar *
のポインタあります。いくつかのコンテキストでは、配列識別子がデコレーションをポインタに渡しますが、ポインタではありません。
ポインタがアドレスアレイが「全部」であるに過ぎない - 最初のケースsizeof(p)
にポインタ(ターゲットマシンに応じて通常4
又は8
)の大きさが得られる、第2の場合には得られます7 * sizeof(char)
、実際の文字列の長さ。
"実行可能ファイルの読み取り専用領域":おそらく "プロセス"はここでより重要です... "実行可能ファイル"プログラムを含むディスクファイルに焦点が当てられていますが、重要なのは、そのファイルコンテンツがコピーされるメモリが、最新のOSローダによって読み取り専用になるということです。私はあなたの2番目の 'p 'を'私 'の下に置いたのが好きです...私の一部は「配列を強調する」の下に置くことを望んでいます... - 配列のオフセットを理解することが重要であるため、しかし、p *がテキストデータを含む配列のすべてであることを強調しましたが、これはこの文脈ではもっと重要です。 +1 –
非常に良い答え。また、グラフィックメソッドは、違いを説明する。 –
@トニー:訂正していただきありがとうございます、私の答えを更新しました。 –
最初の1つは、ポインタを作成し、それを定数文字列のアドレスに設定します(おそらくページの書き込み保護を持たない領域にあります)。このポインタへの書き込みは不正です(おそらくクラッシュします)。
は、配列を作成し、文字をコピーします。この配列に書き込むと、スタック上のある場所に書き込まれ、完全に合法です。
最初のケースでは、Cへのポインタへの書き込みは不正ではありません。未定義の動作です。メモリ保護エラーが発生するか、正常に動作する可能性があります。これは、コンパイラのオペレーティングシステムとマシンアーキテクチャの組み合わせに完全に依存します。 – JeremyP
にリテラル文字列を代入、「文字列」ので、メモリを変更しようと、プロセスの読み取り専用領域に格納することができるのpによって指さだろう未定義の動作が発生します。
上記のコード行を繰り返し実行することで証明できます。
char *p="string";
pの内容(つまり「文字列」のアドレス)が一定のままであることがわかります。
char p[] = "string";
これらのメモリは、pの変更内容を実行するたびに割り当てられます。
[the c-faq](http://c-faq.com/)のセクション6(など)を読むことをお勧めします。 – pmg
は興味深いものが見つかりました:http://www.geeksforgeeks.org/storage-for-strings-in-c/ – NDestiny