メモリ動的割当て

10351 ワード

一般的なデスクトップ・コンポーネントから見ると、ハードウェアには、マザーボード(|マザーボード)、CPU、メイン・メモリ(DRAM)、アシスト・メモリ(SSD、ハード・ディスク)、グラフィックス・カード(GPU)が含まれています.
コンピュータ上では、プログラムは補助メモリに格納され、メインメモリにロードされ、CPU上の演算装置が動作する.記憶空間はメインメモリの記憶空間である.
ストレージスペースは3つの領域に分けることができ、異なる変数はストレージスペースの異なる領域を指定します.
領域
説明:
データ領域
グローバル変数、静的変数の保存/プログラム起動時の割当て、終了時の消滅
ヒープ領域
ユーザーがランダムに割り当てて破棄した領域
/フリーメモリ領域と呼ばれ、実行中にサイズが変化して「メモリの動的割り当て」に使用されます.
スタック領域
領域変数、パラメータ保存/関数呼び出し時に割り当て、終了時に消える

プログラムを実行するには、メインメモリにストレージスペースを割り当てる必要があります.Cで変数を宣言することは、記憶領域を保持することを意味する.
プログラムがメモリを解放する方法は、「静的メモリ割り当て」と「動的メモリ割り当て」の2つです.

メモリ静的割当て


メモリ静的割当て(Memory Static Allocation)とは、プログラムを実行する前に、プログラムの作成段階で必要なメモリ領域のサイズを事前に割り当てることです.ストレージスペースのサイズを事前に決定するため、変数と配列を宣言します.
void memory_static_allocation(){
	int a = 1;
    int array[3] = {1,2,3};
}
上記の例では、関数を呼び出す場合、int型変数「a」は領域変数であるため、スタック領域に割り当てられるサイズは4 byteであり、1が格納される.同様に、3つのint型データを有する配列「array」は、スタック領域に12バイトのサイズで割り当てられ、それぞれ1、2、3が格納される.呼び出しが終了すると、スタック領域から消えます.
int main(){
	char name[20];
    
    printf("이름 : ");
    scanf("%s", name);
    
    printf("입력한 이름 : %s", name);
}
上記のように名前を入力して出力するプログラムがある場合は、各人の名前の文字数が異なる場合があるため、配列のサイズを空きサイズに割り当てる必要があります.これはすぐにストレージスペースの無駄になります.
int main(){
    int size;
    char name[size];

    printf("이름 글자 수 : ");
    scanf("%d", &size);
    
    printf("이름 : ");
    scanf("%s", name);

    printf("입력한 이름 : %s", name);
}
したがって、プログラムを作成するときに上記のように名前の文字数と名前を入力して、ストレージスペースの無駄を減らすと、エラーが発生します.Cは配列の大きさを定数として宣言しなければならないからである.
これらの問題を解決するには、メモリの動的割り当て(Memory Dynamic Assignment)を使用します.

メモリ動的割当て


Memory Dynamic Allocationでは、プログラムの実行時に入力したデータを使用して、お尻の領域に適切なサイズのメモリを割り当てることができます.これにより、メモリの静的割り当てにおけるメモリの浪費問題を迅速に解決できます.
メモリ動的割り当ては、特定の関数を使用して行われます.この関数を使用すると、コンピュータが使用していないメモリ領域を検索して割り当て、その場所を指すポインタに戻るのに時間がかかり、プログラムの実行が遅くなります.したがって、必要に応じてのみ使用することが望ましい.
※メモリ動的割当てで使用する関数を使用するには、#include <stdlib.h>に「stdlib」ヘッダファイルを含める必要があります.

malloc()関数


「malloc()関数」は、hip領域に格納領域をバイト単位で動的に割り当てる割り当てメモリブロックです.void* malloc(size_t size);として使用され、hip領域にバイト単位で記憶空間が割り当てられ、記憶空間の開始アドレスが返される.
メモリ不足などの割り当てに失敗した場合はnullポインタを返します.前処理に失敗した場合はnullポインタは定数0に等しい「0」になります.
malloc()はvoid*を返すため、他のタイプに変換できます.
malloc()は、割り当てられたストレージ領域を初期化しません.
※ size_t : typedef unsigned int size_t;unsigned intをtypedefとして再定義し、size tとして定義します.
しかし、厳密にはunsigned intとは違います.

フリー()関数


hip領域に割り当てると、プログラムを終了するとオペレーティングシステムはメモリを解放しますが、プログラムを終了する前にオペレーティングシステムはメモリを解放します.これはメモリを浪費し、プログラムの実行速度を低下させる可能性があります.また、メモリ容量は限られており、割り当てを続けるとメモリが不足する可能性があります.したがって、free()関数を使用して、使用済みまたは浪費中のメモリを返す必要があります.void free(void *p);の形式で使用され、ポインタの記憶空間を返して解放する.

calloc()関数


calloc()関数は、malloc()関数のようにhip領域にメモリを動的に割り当て、0に初期化する「メモリブロックの割り当てとクリア」です.void* calloc(int n, int size);として使用され、malloc()関数とは異なり、n個のメモリ領域が割り当てられ、失敗したときにnullポインタが返されます.

realloc()関数


realloc()関数は、割り当てられたメモリ領域のサイズを変更できる「resize memory block」です.void* realloc(void *p, int size);の形式で使用され、ポインタpが指す記憶領域のサイズをサイズに変更し、再割り当てされた記憶領域のポインタを返す.
変更するサイズが元のサイズより大きい場合は、元のストレージスペースの後ろに十分なスペースがある場合は、その場所にスペースサイズを追加するだけですが、空でない場合は、十分な大きなストレージスペースに移動して再割り当てし、元のコンテンツを元の場所にコピーします.

きおくくうかんりかんすう


メモリ動的割当て関数を使用してストレージ領域を割り当てた後、ストレージ領域のリソースを使用するには、ストレージ領域管理関数を使用します.
※記憶空間管理に関する関数を使用するには、#include <mem.h>"mem"ヘッダファイルinlcudeを使用する必要があります.

memcmp()関数


「memcmp関数」は、所与のサイズの記憶領域のデータを比較することによって、同じかどうかを決定する「compare memory blocks」です.int memcmp(const void *s1, const void *s2, size_t n);の形式で使用され、s 1とs 2が指す記憶空間の内容はnバイトを比較し、s 1>s 2は正の値を返し、s 1=s 2は0を返し、s 1※memcmp()関数vs strncmp()関数:strncmp()関数の間にNULL文字が入っているので、後の内容が違っても同じと判別しますが、memcmp()関数は最後まで比較するので正確に判別できます.
#include <stdio.h>
#include <string.h>
#include <mem.h>

int main(){
    char *p1 = "abc\0d";
    char *p2 = "abc\0e";

    int a = strncmp(p1, p2, 5);
    int b = memcmp(p1, p2, 5);

    printf("%d\n", a);
    printf("%d\n", b);
}
0
-1

memcpy()関数


「memcpy()関数」は、記憶領域内のデータを別の記憶領域にコピーするための「copy memory block」です.void* memcpy(void *dest, const void *src, size_t n);として使用し、src(ソース)のターゲットデータをdest(ターゲット)のnバイトにコピーし、destの値を返します.

memset()関数


「memset()関数」は、指定した文字で記憶領域を埋め込む「initialize memory block」です.void* memset(void *s, int c, size_t n);の形式で使用され、sで表される記憶空間はcの値でnバイトを充填し、sの値を返す.