1

ここでは、文字列の特定の文字を変更できるように p にメモリを動的に割り当てていますが、このコードは途中でハングします

 int main()
 {
  char *p;
  p=malloc(10*sizeof(char));
  p="string";
  p[0]='d';
  printf("%s",p);
 }

p="string"5 行目を次のように置き換えてみましたstrcpy(p, "string")が、コードは完全に機能しました。誰かこの理由を教えてください。

 int main()
 {
   char *p;
   p=malloc(10*sizeof(char));
   strcpy(p, "string");
   p[0]='d';
   printf("%s",p);
 }
4

5 に答える 5

2

ポインターは、リソース (malloc) を所有するか、別のエンティティーによって既に所有されているリソースを指すことができます。を行うと、文字ポインターを割り当てる をp="string";作成しています。前の行で malloc されたメモリをリークすることにより、後者では、malloc されたメモリ内の内容を置き換えるだけです。前者はバグ/問題ですが、後者はそうではありません。リソース/メモリをリークすることは悪い習慣ですが、ハングの背後にある理由ではないことに注意してください。const char *p

ハングする理由は、フードの下で C コードで行う編集が、プログラムの読み取り専用メモリ空間を編集しようとするためです (const char *変数は、プログラム メモリのこのセグメントで不変のバイト配列として作成されます)。c++ はいつ文字列リテラルを割り当て/割り当て解除しますか で、これについてさらに説明します。

必要なバイトを に渡すことに関してはmalloc、式で type を使用しないようにすることをお勧めします。

const size_t count_required = 10;
char *p = malloc(sizeof(*p) * count_required);
// changing p's type to int* would also work without editing the malloc argument

p の型が、たとえば 、または他の型に変更された場合、式は変更floatなしintで引き続き正常に機能します。

于 2013-01-31T16:58:56.390 に答える
1

C では、文字列は値ではありません。割り当て ( ) を使用して文字列をコピーすることはできません=が、ポインターを割り当てることはできます (ポインターは「実際の」値です)。

新しく割り当てられたメモリに文字列をコピーするには、次のものが必要です。

strcpy(p, "string");

あなたが書いた方法では、返されたポインタmalloc()を静的文字列定数のアドレスで上書きしています。これにより、メモリ リークが発生します。それらを回避することは、C をプログラムするのに非常にやりがいのある言語にする課​​題の 1 つです。

于 2013-01-31T17:00:08.053 に答える
1

この線

 p="string";

p読み取り専用の文字列リテラルを指すように変更され、プロセスで以前に割り当てられたメモリがリークします。文字列リテラルに書き込むことはできないためp[0]='d';、セグ フォールトが発生する可能性があります。

あなたの2番目のバージョンは、使用します

strcpy(p, "string");

読み取り専用文字列リテラルの内容を、以前に割り当てたメモリにコピーします。ここで動的に割り当てたバッファーを引き続き使用しているため、後のコードで内容を変更しても安全です。

もう1つの非常にマイナーなポイントは、 1であることが保証されているため、呼び出しをsizeof(char)簡素化できますmalloc

 p=malloc(10);
于 2013-01-31T16:57:48.557 に答える
0

まず、最初のプログラムにメモリ リークがあります。malloc次に、ポインターを別の定数文字列に割り当てます。

次に、最初のプログラムでは、定数文字列を変更しています。しかし、2番目の「正しい」プログラムでは、その定数文字列を複製し、割り当てられたメモリにコピーしています。自由に変更できます。

于 2013-01-31T16:59:54.383 に答える
0

char amessage[] = "now is the time"; /* an array */

char *pmessage = "now is the time"; /* a pointer */

"amessageは配列で、文字のシーケンスを保持するのに十分な大きさであり、'\0'それを初期化します。配列内の個々の文字は変更される可能性がありますが、メッセージは常に同じストレージを参照します。一方、pmessageは文字列を指すように初期化されたポインターです。定数; ポインターは後で別の場所を指すように変更される可能性がありますが、文字列の内容を変更しようとした場合の結果は未定義です。」

礼儀K&R

于 2013-01-31T17:05:33.377 に答える