2011-06-29 22 views
11
char *p = "string"; //creates pointer to constant string 

char p[] = "string"; //just an array with "string" 

なぜ私は最初の例で定数文字列へのポインタを作成するのですか?それは単に "文字列"を持つメモリ内の場所を参照するポインタではないでしょうか?Cのconst文字列へのポインタ

+0

[the c-faq](http://c-faq.com/)のセクション6(など)を読むことをお勧めします。 – pmg

+0

は興味深いものが見つかりました:http://www.geeksforgeeks.org/storage-for-strings-in-c/ – NDestiny

答えて

14

残念なことに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 
21

最初のケースでは、"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)、実際の文字列の長さ。

+0

"実行可能ファイルの読み取り専用領域":おそらく "プロセス"はここでより重要です... "実行可能ファイル"プログラムを含むディスクファイルに焦点が当てられていますが、重要なのは、そのファイルコンテンツがコピーされるメモリが、最新のOSローダによって読み取り専用になるということです。私はあなたの2番目の 'p 'を'私 'の下に置いたのが好きです...私の一部は「配列を強調する」の下に置くことを望んでいます... - 配列のオフセットを理解することが重要であるため、しかし、p *がテキストデータを含む配列のすべてであることを強調しましたが、これはこの文脈ではもっと重要です。 +1 –

+0

非常に良い答え。また、グラフィックメソッドは、違いを説明する。 –

+0

@トニー:訂正していただきありがとうございます、私の答えを更新しました。 –

3

最初の1つは、ポインタを作成し、それを定数文字列のアドレスに設定します(おそらくページの書き込み保護を持たない領域にあります)。このポインタへの書き込みは不正です(おそらくクラッシュします)。

は、配列を作成し、文字をコピーします。この配列に書き込むと、スタック上のある場所に書き込まれ、完全に合法です。

+0

最初のケースでは、Cへのポインタへの書き込みは不正ではありません。未定義の動作です。メモリ保護エラーが発生するか、正常に動作する可能性があります。これは、コンパイラのオペレーティングシステムとマシンアーキテクチャの組み合わせに完全に依存します。 – JeremyP

1

にリテラル文字列を代入、「文字列」ので、メモリを変更しようと、プロセスの読み取り専用領域に格納することができるのpによって指さだろう未定義の動作が発生します。

上記のコード行を繰り返し実行することで証明できます。

char *p="string"; 

pの内容(つまり「文字列」のアドレス)が一定のままであることがわかります。

char p[] = "string"; 

これらのメモリは、pの変更内容を実行するたびに割り当てられます。

関連する問題