私が理解していることから、malloc 関数は変数を取り、要求に応じてメモリを割り当てます。この場合、20 個の double 変数の同等性に適合するようにメモリを準備するようにコンパイラに要求します。それを正しく理解する私の方法はありますか?なぜそれを使用する必要があるのですか?
double *q;
q=(double *)malloc(20*sizeof(double));
for (i=0;i<20; i++)
{
*(q+i)= (double) rand();
}
私が理解していることから、malloc 関数は変数を取り、要求に応じてメモリを割り当てます。この場合、20 個の double 変数の同等性に適合するようにメモリを準備するようにコンパイラに要求します。それを正しく理解する私の方法はありますか?なぜそれを使用する必要があるのですか?
double *q;
q=(double *)malloc(20*sizeof(double));
for (i=0;i<20; i++)
{
*(q+i)= (double) rand();
}
malloc()
次の場合は使用する必要はありません。
malloc()
コンパイル時ではなく、実行時にメモリを割り当てることに注意してください。コンパイラは、正しい関数が呼び出されることを保証する範囲でのみ関与します。それがmalloc()
割り当てを行います。
あなたの例では、「10個の整数の同等性」について言及しています。double
20が 10 と同じスペースを占有することはめったにありませんint
。通常、10double
は 20 と同じスペースを占有しますint
(非常に一般的な設定である と の場合sizeof(int) == 4
) sizeof(double) == 8
。
コンパイル時ではなく実行時にメモリを割り当てるために使用されます。したがって、データ配列がユーザー、データベース、ファイルなどからの何らかの入力に基づいている場合malloc
は、目的のサイズが判明したら使用する必要があります。
変数q
はポインタです。つまり、アドレスをメモリに格納します。malloc
は、メモリのセクションを作成し、メモリのそのセクションのアドレスを返すようにシステムに要求しています。これは に格納されていq
ます。Soq
は、要求したメモリの開始位置を指します。
q
意図せずに変更しないように注意する必要があります。たとえば、次のようにします。
q = (double *)malloc(20*sizeof(double));
q = (double *)malloc(10*sizeof(double));
20 の最初のセクションにアクセスできなくなりdouble
、メモリ リークが発生します。
を使用するときmalloc
は、システムに「ねえ、このバイト数のメモリが欲しい」と尋ねると、システムは「申し訳ありませんが、すべて終了しました」または「わかりました。これが必要なメモリのアドレスです。ドン」と言います。失うな」。
一般に、大きなデータセットをヒープ (malloc
メモリを取得する場所) に配置し、そのメモリへのポインタをスタック (コードの実行場所) に配置することをお勧めします。これは、メモリが限られている組み込みプラットフォームではより重要になります。スタックとヒープの間で物理メモリをどのように分割するかを決定する必要があります。スタックが多すぎると、多くのメモリを動的に割り当てることができません。スタックが少なすぎると、すぐに関数を呼び出すことができます(スタックオーバーフローとも呼ばれます:P)
他の人が言ったように、mallocはメモリを割り当てるために使用されます。mallocはヒープからメモリを割り当てるため、メモリはfree
'dになるまで永続的であることに注意することが重要です。それ以外の場合、mallocを使用せずに、のようなものを宣言するdouble vals[20]
と、スタックにメモリが割り当てられます。関数を終了すると、そのメモリはスタックからポップされます。
たとえば、関数内にいて、値の永続性を気にしないとします。次に、以下が適切です。
void some_function() {
double vals[20];
for(int i = 0; i < 20; i++) {
vals[i] = (double)rand();
}
}
ここで、関数だけよりも存続期間が長いグローバル構造またはデータを格納するものがある場合は、mallocを使用してヒープからそのメモリを割り当てる必要があります(または、グローバル変数として宣言することもできます。メモリは事前に割り当てられます)。
あなたの例では、double q[20];
なしで宣言でき、malloc
それは機能します。
malloc
動的に割り当てられたメモリを取得する標準的な方法です ( Linuxmalloc
のような低レベルのメモリ取得プリミティブの上に構築されることがよくありますmmap
)。
特に、割り当てられたもの (ここではq
ポインター) のサイズが実行時パラメーターに依存する場合 (たとえば、入力に依存する場合)、動的に割り当てられたメモリ リソースを取得する必要があります。悪い代替案は、すべてを静的に割り当てることですが、データの静的サイズは組み込みの強力な制限であり、それは好きではありません。
動的リソース割り当てにより、安価なタブレット (0.5 ギガバイトの RAM) と高価なスーパーコンピューター (テラバイトの RAM) で同じプログラムを実行できます。異なるサイズのデータを割り当てることができます。
malloc
;の結果をテストすることを忘れないでください。NULL を返すと失敗する可能性があります。少なくとも、次のようにコーディングします。
int* q = malloc (10*sizeof(int));
if (!q) {
perror("q allocation failed");
exit(EXIT_FAILURE);
};
常に malloc
-edメモリを初期化します(割り当てられたメモリをゼロにするものを使用することをお勧めしますcalloc
)。
-ed メモリを後で忘れないでくださいfree
。malloc
Linux では、valgrindの使用について学習します。メモリ リークやダングリング ポインタに注意してください。一部のデータの活性は、プログラム全体のモジュール化されていないプロパティであることを認識してください。ガベージ コレクション!について読んで、おそらくBoehm の保守的なガベージ コレクタのGC_malloc
使用を検討してください ( の代わりに呼び出してmalloc
)。
malloc()
でメモリを動的に割り当てるために使用しC
ます。(でメモリを割り当てrun time
ます) プログラムを書くときにどれだけのメモリを使用するかわからない場合があるため、これを使用します。コンパイル時に配列が保持する要素の数がわかっている場合は、使用する必要はありません。
関数から配列を返したい場合は、スタック上の関数内で定義されていない配列を返す必要があることに注意してください。代わりに、( heapに)配列を動的に割り当てて、このブロックへのポインターを返す必要があります。
int *returnArray(int n)
{
int i;
int *arr = (int *)malloc(sizeof(int) * n);
if (arr == NULL)
{
return NULL;
}
//...
//fill the array or manipulate it
//...
return arr; //return the pointer
}