0

メモリを動的に割り当てるには 4 つの方法がありますが、4 つの方法に違いはありますか? 最初にこのように:

char *seq=(char *)malloc(100*sizeof(char));
void exam(char *seq){
    // using 'seq'
}

このように2番目:

char *seq;
void exam(char *seq){
    seq=(char *)malloc(100*sizeof(char));
    // using 'seq'
}

3番目に次のように:

char *seq=(char *)malloc(10*sizeof(char));
void exam(char *seq){
    char *change=(char *)malloc(100*sizeof(char));
    free(seq);
    seq=change;
    // using 'seq'
}

このように4番目:

char *seq=(char *)malloc(100*sizeof(char));
void exam(char *seq){
    free(seq);
    seq=(char *)malloc(100*sizeof(char));
    //using 'seq'
}

そして、あなたはそれを知っているべきです、私はメソッド「exam」の外で変数「seq」を使用します。 上記のコードを説明してください、どうもありがとうございました。

4

6 に答える 6

2

試験以外で seq を使用する場合は、最初のケースのみが有効です。

他の 3 つのケースは、seq に割り当てられたアドレスを受け取りますが、それを変更することはできません。

seq の値を変更するには、新しい値を返すか、seq の内容を明示的に変更する必要があります。

これが機能しない理由を理解するには、値渡しを調査する必要があります。このページを参照してください。

于 2009-08-07T03:22:33.357 に答える
1

それはすべて、あなたが何をしようとしているのかにかかっています。可能であれば、IMO と同じスコープで malloc/free を実行することをお勧めします。これにより、コードがはるかに読みやすくなります。C でのメモリ割り当ては、すでに十分に困難です。あなたの場合、最初にmallocし、関数を呼び出し、関数の外で解放します。しかし、もちろん、それが常に可能であるとは限りません。

あなたの解決策のいくつかはうまくいきません.例えば、2番目のものはあなたが望むことをしません.関数を呼び出すとポインタがコピーされるからです.

char *p;
function(p);

void function(char *q) {
    // q is a copy of p, so when q is set by malloc, it will not be reflected in p
    q = malloc(100);
}

一般に、fopen 関数と同じように行う必要があります。ポインターを返します。

char* p function() {
    char* ret;
    ret = malloc(100);
    return ret;
}

char *p = function();

または、ポインターへのポインターを使用できます。

char *p;
function(&p);

void function(char **q) {
    // q is a copy of &p, so when *q is set by malloc, it is the same memory location as &p
    *q = malloc(100);
}

ただし、一般的には、最初のものがはるかに優れていると思います。

また、あなたのスタイルに関して: sizeof(char) は役に立たず、使用しているコンパイラ/プラットフォームに関係なく、定義により常に 1 に等しく、malloc のキャストは役に立たず、実際には危険です (malloc が宣言されている場所に欠落しているヘッダーのインクルードを隠すため) )。これは、C++ で malloc を使用する場合にのみ役立ちます (キャストが必須である場合)。

于 2009-08-07T03:23:15.650 に答える
1

1989 ANSI 標準より前の C の実装を使用している場合、またはこのコードを C++ としてコンパイルする場合を除き、malloc() の結果をキャストしないでください。まず第一に、それは必要ありません。第二に、スコープ内に malloc() のプロトタイプがない場合、コンパイラの診断がマスクされます。

また、sizeof(char) は定義上 1 です。この場合に使用しても違いはなく、視覚的なノイズが追加されるだけです。

任意の型 T の malloc() ステートメントを記述するための標準的な形式は次のとおりです。

T *p = malloc(count * sizeof *p);

また

T *p;
...
p = malloc(count * sizeof *p);

今あなたの4つのケースに対処しています...

最初のケースは一般的に正しいです。試験の外で seq にメモリを割り当て、ポインターを値で渡します。

残りのケースはすべて同様の問題を抱えています。ポインター値 seq への変更は呼び出し元に反映されず、メモリ リークが発生します。関数にポインターを渡し、ポインター値を上書きしたい場合は、そのポインターにポインターを渡す必要があります。

char *seq;
exam(&seq);
...
void exam(char **seq) { *seq = malloc(100); ... }

動的に割り当てられたバッファーのサイズを変更する場合は、realloc() を使用します。

char *seq = malloc(10);
exam(&seq);
...
void exam(char **seq) 
{
  char *tmp = realloc(*seq, 100);
  if (!tmp) 
  {
    /* realloc failed */
  }
  else
  {
    *seq = tmp;
    ...
  }

ご了承ください

char *p = realloc(NULL, 10);

と同じです

char *p = malloc(10);
于 2009-08-07T17:58:47.940 に答える
1

あなたがしていることを行うには、おそらく多くの方法があります。関数の外で seq を使用する場合は、最初に概説した方法が機能します。

関数を呼び出した後に seq を使用する場合、他のメソッドには他の問題があります。C は値渡しであるため、seq に含まれるアドレスをルーチンに渡しますが、最後の 3 つの例で seq に関連付けられたメモリ位置は変更されません。seq のメモリ位置を変更するには、ポインタのアドレスをルーチンに渡してポインタを設定する必要があります。これは David Cournapeau の例に示されています。

最後の 2 つのケースの問題は、メモリを「解放」したことですが、seq の値は変更されず、「解放」したメモリにアクセスするために使用できるため、メモリへのポインタを保持したままです。これは、ダングリング ポインターとして知られています。

関数を使用してポインターを返すという David Cournapeau の提案により、関数で割り当てたメモリにアクセスできるようになります。それ以外の場合は、seq のアドレスをルーチンに渡し、値を逆参照して、割り当てられたスペースに設定する必要があります。

于 2009-08-07T04:12:02.353 に答える
0

これらは範囲の違いだと思います

于 2009-08-07T03:16:09.497 に答える
0

状況に光を当てるために、次の書き直しを検討してください。

char *seq=(char *)malloc(100*sizeof(char));
void exam(char *var){
    // using 'var'
}
//--
char *seq;
void exam(char *var){
    var=(char *)malloc(100*sizeof(char));
    // using 'var'
}
//--
char *seq=(char *)malloc(10*sizeof(char));
void exam(char *var){
    char *change=(char *)malloc(100*sizeof(char));
    free(var);
    var=change;
    // using 'var'
}
//--
char *seq=(char *)malloc(100*sizeof(char));
void exam(char *var){
    free(var);
    var=(char *)malloc(100*sizeof(char));
    //using 'var'
}

電話すると

exam(seq);

上記のバージョンはオリジナルと同じです。

于 2009-08-07T03:26:40.353 に答える