6

C で通常の配列定義の代わりに malloc を使用する必要があるのはいつですか?

次の違いがわかりません。

int a[3]={1,2,3}
int array[sizeof(a)/sizeof(int)]

と:

array=(int *)malloc(sizeof(int)*sizeof(a));
4

4 に答える 4

19

一般に、次の場合に使用malloc()します。

  • 配列が大きすぎてスタックに配置できません
  • 配列の有効期間は、配列が作成されたスコープよりも長く存続する必要があります

それ以外の場合は、スタックに割り当てられた配列を使用します。

于 2012-06-28T08:50:38.073 に答える
6
int a[3]={1,2,3}
int array[sizeof(a)/sizeof(int)]

ローカル変数として使用する場合、との両方aarrayスタックに割り当てられます。スタック割り当てには長所と短所があります。

  • プロ:非常に高速です。スタックスペースを作成するのに1回のレジスタ減算操作と、それを再利用するのに1回のレジスタ追加操作のみが必要です。
  • 短所:スタックサイズは通常制限されています(Windowsではリンク時にも修正されます)

どちらの場合も、各配列の要素数はコンパイル時定数です。が宣言された時点でのサイズとのサイズの両方がわかっているため、コンパイル時に計算できる3のは明らかに定数です。sizeof(a)/sizeof(int)aintarray

要素の数が実行時にのみわかっている場合、または配列のサイズが大きすぎてスタックスペースに安全に収まらない場合は、ヒープ割り当てが使用されます。

array=(int *)malloc(sizeof(int)*sizeof(a));

すでに指摘したように、これはmalloc(sizeof(a))、のサイズaがすでに必要なバイト数であり、要素の数ではないため、追加の乗算sizeof(int)は必要ないためです。

ヒープの割り当てと割り当て解除は(スタックの割り当てと比較して)比較的コストのかかる操作であり、これは、たとえばタイトなループで何度も呼び出されるコードなど、それが提供する利点と慎重に比較検討する必要があります。

最新のCコンパイラは、他の言語で利用可能な同様の機能に似た、いわゆる可変長配列(またはVLA)を導入するC標準のC99バージョンをサポートしています。VLAのサイズは、次のように実行時に指定されます。

void func(int n)
{
   int array[n];
   ...
}

array配列のメモリがへの呼び出しによって割り当てられたかのように、スタックに割り当てられますalloca(3)

于 2012-06-28T10:21:40.337 に答える
2

配列のサイズを固定したくない場合は、間違いなくmalloc()を使用する必要があります。何をしようとしているのかによって、特定のタスクに必要なメモリ量が事前にわからない場合や、実行時に配列のサイズを動的に変更する必要がある場合があります。たとえば、データが多い場合は配列を拡大する場合があります。後者は、データを失うことなくrealloc()を使用して実行できます。

元の投稿のように配列を初期化する代わりに、整数へのポインタを初期化する必要があります。

int* array; // this variable will just contain the addresse of an integer sized block in memory
int length = 5; // how long do you want your array to be;

array = malloc(sizeof(int) * length); // this allocates the memory needed for your array and sets the pointer created above to first block of that region;

int newLength = 10;
array = realloc(array, sizeof(int) * newLength); // increase the size of the array while leaving its contents intact;
于 2012-06-28T09:08:20.003 に答える
1

あなたのコードはとても奇妙です。

タイトルの質問に対する答えは、おそらく「短期間の非常に少量のデータが必要な場合は自動的に割り当てられた配列を使用し、他の用途にはヒープ割り当てを使用malloc()する」のようなものです。しかし、正確な答えを特定するのは難しいです。それは状況に大きく依存します。

最初に配列を表示し、次に最初の配列からその長さを計算しようとする別の配列を表示し、最後にmalloc()同じことを実行しようとする呼び出しを表示している理由がわかりません。

通常、模倣したいサイズの既存の配列ではなく、必要な要素の数がわかります。

2行目は次のように優れています。

int array[sizeof a / sizeof *a];

のタイプへの依存関係を繰り返す必要はありません。上記は、配列と同じ数の要素を持つの配列としてa定義されます。これは、が実際に配列である場合にのみ機能することに注意してください。arrayintaa

また、3行目はおそらく次のようになります。

array = malloc(sizeof a);

sizeof引数について(特に間違っているので)賢くなりすぎる必要はなく、の戻り値をキャストする必要もありませんmalloc()

于 2012-06-28T08:47:38.363 に答える