malloc()、calloc() 関数を使用した C での動的メモリ割り当て
C の動的メモリ割り当てを学ぶ前に、次のことを理解しましょう。
C のメモリ管理はどのように機能するのでしょうか?
基本データ型を使用して変数を宣言すると、C コンパイラは、 スタック.
たとえば、float 変数は、宣言時に通常 (プラットフォームに応じて) 4 バイトかかります。 この情報は、 のサイズ 下記の例に示すような演算子
#include <stdio.h> int main() { float x; printf("The size of float is %d bytes", sizeof(x)); return 0;}
出力は次のようになります。
The size of float is 4 bytes
また、指定されたサイズの配列はメモリの連続したブロックに割り当てられ、各ブロックは XNUMX つの要素のサイズになります。
#include <stdio.h> int main() { float arr[10]; printf("The size of the float array with 10 element is %d", sizeof(arr)); return 0;}
結果は次のとおりです。
The size of the float array with 10 element is 40
これまで学習したように、基本的なデータ型または配列を宣言すると、メモリは自動的に管理されます。 ただし、C にはメモリを割り当てるプロセスがあり、これを使用すると、プログラムを実行する (ランタイム) まで配列サイズが決定しないプログラムを実装できます。 このプロセスは「」と呼ばれます。動的メモリ割り当てに設立された地域オフィスに加えて、さらにローカルカスタマーサポートを提供できるようになります。」
C での動的メモリ割り当て
動的メモリ割り当て プログラミングのニーズに応じてメモリを手動で割り当てたり解放したりすることです。 動的メモリは、ヒープと呼ばれる領域内に新しく割り当てられたメモリ空間を指すポインタによって管理および提供されます。
これで、実行時に問題なく要素の配列を動的に作成および破棄できるようになりました。 要約すると、自動メモリ管理ではスタックが使用され、C の動的メモリ割り当てではヒープが使用されます。
のライブラリには、動的メモリ管理を担当する関数があります。
演算 | 目的 |
---|---|
malloc() | 要求されたサイズのメモリを割り当て、その最初のバイトへのポインタを返します。 割り当てられたスペース。 |
calloc() | 配列の要素にスペースを割り当てます。 要素をゼロに初期化し、メモリへのポインタを返します。 |
realloc() | 以前に割り当てられたメモリ空間のサイズを変更するために使用されます。 |
無料() | 以前に割り当てられたメモリ空間を解放または空にします。 |
上記の関数とその応用について説明しましょう
C の malloc() 関数
C の malloc() 関数はメモリ割り当てを表します。 これは、メモリのブロックを動的に割り当てるために使用される関数です。 指定されたサイズのメモリ空間を予約し、メモリ位置を指す null ポインタを返します。 返されるポインタは通常、void 型です。 これは、C の malloc() 関数を任意のポインターに割り当てることができることを意味します。
malloc() 関数の構文:
ptr = (cast_type *) malloc (byte_size);
ここでは、
- ptr は、cast_type のポインタです。
- C の malloc() 関数は、byte_size の割り当てられたメモリへのポインタを返します。
malloc() の例:
Example: ptr = (int *) malloc (50)
このステートメントが正常に実行されると、50 バイトのメモリ空間が予約されます。 予約領域の最初のバイトのアドレスは、int 型のポインタ ptr に割り当てられます。
別の例を考えてみましょう。
#include <stdlib.h> int main(){ int *ptr; ptr = malloc(15 * sizeof(*ptr)); /* a block of 15 integers */ if (ptr != NULL) { *(ptr + 5) = 480; /* assign 480 to sixth integer */ printf("Value of the 6th integer is %d",*(ptr + 5)); } }
出力:
Value of the 6th integer is 480
- 注意してください sizeof(*ptr) の代わりに使用されました サイズ(int) *ptr 宣言が後で別のデータ型に型変換されるときにコードをより堅牢にするためです。
- メモリが十分でない場合、割り当てが失敗する可能性があります。 この場合、NULL ポインタが返されます。 したがって、NULL ポインターをチェックするコードを含める必要があります。
- 割り当てられたメモリは連続しており、配列として扱うことができることに注意してください。配列要素にアクセスするには、括弧 [ ] を使用する代わりに、ポインタ演算を使用できます。配列要素を参照するには、インクリメント ++ または += を使用すると、配列に格納されているアドレスが変更されるため、+ を使用することをお勧めします。 ポインタ.
Malloc() 関数は、構造体などの複雑なデータ型だけでなく、文字データ型でも使用できます。
C の free() 関数
の記憶 variables コンパイル時に自動的に割り当てが解除されます。 動的メモリ割り当てでは、メモリの割り当てを明示的に解除する必要があります。 これを行わないと、メモリ不足エラーが発生する可能性があります。
無料() C では、メモリを解放/割り当て解除するために関数が呼び出されます。プログラムでメモリを解放すると、後で使用できるメモリが増えます。
例:
#include <stdio.h> int main() { int* ptr = malloc(10 * sizeof(*ptr)); if (ptr != NULL){ *(ptr + 2) = 50; printf("Value of the 2nd integer is %d",*(ptr + 2)); } free(ptr); }
出力:
Value of the 2nd integer is 50
C の calloc() 関数
C の calloc() 関数は連続割り当てを表します。この関数は、複数のメモリ ブロックを割り当てるために使用されます。これは、配列や構造体などの複雑なデータ構造にメモリを割り当てるために使用される動的なメモリ割り当て関数です。
Malloc() 関数はメモリ空間の単一ブロックを割り当てるために使用され、C の calloc() はメモリ空間の複数のブロックを割り当てるために使用されます。 calloc() 関数によって割り当てられた各ブロックは同じサイズです。
calloc() 関数の構文:
ptr = (cast_type *) calloc (n, size);
- 上記のステートメントは、同じサイズの n 個のメモリ ブロックを割り当てるために使用されます。
- メモリ空間が割り当てられた後、すべてのバイトがゼロに初期化されます。
- 現在、割り当てられたメモリ空間の最初のバイトにあるポインタが返されます。
メモリ不足などメモリ空間の割り当てにエラーが発生した場合は、必ず null ポインタが返されます。
calloc() の例:
以下のプログラムは等差数列の和を計算します。
#include <stdio.h> int main() { int i, * ptr, sum = 0; ptr = calloc(10, sizeof(int)); if (ptr == NULL) { printf("Error! memory not allocated."); exit(0); } printf("Building and calculating the sequence sum of the first 10 terms \ n "); for (i = 0; i < 10; ++i) { * (ptr + i) = i; sum += * (ptr + i); } printf("Sum = %d", sum); free(ptr); return 0; }
結果:
Building and calculating the sequence sum of the first 10 terms Sum = 45
calloc() と malloc(): 主な違い
以下は、 malloc() と calloc() Cで:
一般的に、calloc() 関数は malloc() 関数よりも適切で効率的です。両方の関数はメモリ空間を割り当てるために使用されますが、calloc() は一度に複数のブロックを割り当てることができます。毎回メモリ ブロックを要求する必要はありません。calloc() 関数は、より大きなメモリ空間を必要とする複雑なデータ構造で使用されます。
C の calloc() によって割り当てられたメモリ ブロックは常にゼロに初期化されますが、C の関数 malloc() では常にガベージ値が含まれます。
C の realloc() 関数
C の使用 realloc() 関数を使用すると、すでに割り当てられているメモリにさらにメモリ サイズを追加できます。 元の内容をそのままにして、現在のブロックを展開します。 C の realloc() はメモリの再割り当てを表します。
realloc() を使用して、以前に割り当てられたメモリのサイズを削減することもできます。
realloc() 関数の構文:
ptr = realloc (ptr,newsize);
上記のステートメントは、変数 newsize で指定されたサイズの新しいメモリ空間を割り当てます。 関数の実行後、ポインタはメモリ ブロックの最初のバイトに返されます。 新しいサイズは、以前のメモリより大きくても小さくても構いません。 新しく割り当てられたブロックが以前のメモリ ブロックと同じ場所を指すかどうかはわかりません。 この関数は、以前のすべてのデータを新しい領域にコピーします。 データの安全性が確保されます。
realloc() の例:
#include <stdio.h> int main () { char *ptr; ptr = (char *) malloc(10); strcpy(ptr, "Programming"); printf(" %s, Address = %u\n", ptr, ptr); ptr = (char *) realloc(ptr, 20); //ptr is reallocated with new size strcat(ptr, " In 'C'"); printf(" %s, Address = %u\n", ptr, ptr); free(ptr); return 0; }
C の realloc() が失敗した場合は必ず null ポインターが返され、以前のデータも解放されます。
C の動的配列
C の動的配列を使用すると、必要に応じて要素の数を増やすことができます。C の動的配列は、コンピューター サイエンスのアルゴリズムで広く使用されています。
次のプログラムでは、動的配列を作成し、サイズを変更しました。 C
#include <stdio.h> int main() { int * arr_dynamic = NULL; int elements = 2, i; arr_dynamic = calloc(elements, sizeof(int)); //Array with 2 integer blocks for (i = 0; i < elements; i++) arr_dynamic[i] = i; for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]); elements = 4; arr_dynamic = realloc(arr_dynamic, elements * sizeof(int)); //reallocate 4 elements printf("After realloc\n"); for (i = 2; i < elements; i++) arr_dynamic[i] = i; for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]); free(arr_dynamic); }
画面上の C 動的配列プログラムの結果:
arr_dynamic[0]=0 arr_dynamic[1]=1 After realloc arr_dynamic[0]=0 arr_dynamic[1]=1 arr_dynamic[2]=2 arr_dynamic[3]=3
まとめ
- 必要に応じてヒープ内にメモリ ブロックを作成することで、メモリを動的に管理できます。
- C の動的メモリ割り当てでは、メモリは実行時に割り当てられます。
- 動的なメモリ割り当てにより、サイズが柔軟でプログラム内でいつでも変更できる文字列と配列を操作できます。
- これは、特定の構造体がどれだけのメモリを占有するかわからない場合に必要です。
- C の Malloc() は動的メモリ割り当て関数であり、特定のサイズのメモリ ブロックがガベージ値に初期化されるメモリ割り当てを表します。
- C の Calloc() は、0 に初期化されて一度に複数のメモリ ブロックを割り当てる連続メモリ割り当て関数です。
- C の Realloc() は、指定されたサイズに従ってメモリを再割り当てするために使用されます。
- Free() 関数は、動的に割り当てられたメモリをクリアするために使用されます。