0

バックグラウンド:


これはすべて、友人が file を使用して作成したプログラムから始まりました。

他の詳細はスキップして、実際に私の注意を引いたものに焦点を当てます。

  1. ファイルには、文字列として抽出する必要があるテキストがあります。
  2. 弦の長さが異なる場合があります。
  3. これを達成し、余分な 1 バイトを費やさないようにするために、彼は動的メモリ割り当てを使用しました。彼は最初にサイズを数えてから、malloc で適切なサイズの文字列を作成し、対象の文字列に文字を挿入しました。

それは良いのですが、余分なバイトなしで文字列に文字を格納する別の方法があるかどうかを考えがちです。

私は次のプログラムを持ってきました:

コード:


/* 簡単にするために、ファイルの代わりに、ここでは別の文字列 "c" を使用しました。ここからデータをコピーする必要があります。ch を File からの読み取り文字と見なします。

# include <stdio.h>
# include <string.h>

void main()
{
char *s,*p;
char c[4] ="abc";

char q[2] = "";
s=q;

int i;
for(i=0;c[i]!='\0';i++)
{
    char ch = c[i];
    int len = strlen(s);
    char p[len+2];
    strcpy(p,s);
    p[len]=ch;
    p[len+1]='\0';
    printf("%s\n",p);
    s=p;
}
char t[strlen(s)+1];
strcpy(t,s);

printf("%s\n",t);  //EDIT for understanding: If I print s here it prints garbage, 
                          but if I see the value of s through debugger, it gives
                          correct value?
}

理解:


  1. 文字列 p は for ループにスコープされており、反復ごとに新しい定義を取得しています。
  2. 文字列の開始アドレスは変数 s に保存されるため、コードがスコープ外に出た場合でもメモリにアクセスできます。これは、新しい文字が検出されたときに文字列のサイズを決定するために使用されます。

質問:


1.上記の私の理解が正しければ、何かが欠けています。strcpy s を t に出力して t を出力する (正しい O/P が得られる) 代わりに、直接 s を出力しようとするとガベージが出力されるためです。この動作についてよくわかりませんか?

2.このプログラムでメモリが破損する可能性はありますか?

PS:複数の strcpy() が過剰に殺されていることを理解しています。したがって、プログラムは最適化されていませんが、この動作を理解するためにこの質問をするだけです。

4

2 に答える 2

1

変数の有効期間が終了すると、コンパイラは必要に応じてメモリを自由に再利用できます。「新しい」 p を作成するとき (次回のループのラウンド、およびループの終了後) に「古い」 p へのポインターを保持しても、まったく機能するとは限りません。私はこれが確実に機能するとは思っていません。古い ps と新しい ps が重複する可能性が非常に高いです。

strcpy を使用する場合でも、その他の手法を使用する場合でも、malloc を単純に使用したり、必要に応じて再割り当てを行ったりする場合と比較して、継続的なデータのシャッフルには多くのコストがかかります。

于 2013-08-06T18:21:27.107 に答える
0

in mains と p はポインターとして定義されています。char *s, *p 後で for ループの後で、s の出力とガベージの取得について尋ねます。これsはポインターであり、printf がそのアドレスを出力しようとしているprintf("%p", s);ためprintf("%c", *s);です。 sによって指摘されました。

for ループ内で、p[len+2]この定義という名前の変数を定義しました。これは の宣言を隠しmainます。一般に、これは悪い習慣です。本当に 1) p の 2 番目のバージョンを定義するつもりだったのですか、それとも 2) p が指す場所に情報を保存したいのですか?

1) p の名前を別の名前に変更すると、バグが明らかになります。2)pが指すストレージを割り当ててから、forループから入力します。

あなたの意図を理解し、これがお役に立てば幸いです。

于 2013-08-06T22:49:47.557 に答える