C言語で動的にメモリ確保する方法を教えて!
こういった悩みにお答えします.
本記事の信頼性
- リアルタイムシステムの研究歴12年.
- 東大教員の時に,英語でOS(Linuxカーネル)の授業.
- 2012年9月~2013年8月にアメリカのノースカロライナ大学チャペルヒル校(UNC)コンピュータサイエンス学部で客員研究員として勤務.C言語でリアルタイムLinuxの研究開発.
- プログラミング歴15年以上,習得している言語: C/C++,Python,Solidity/Vyper,Java,Ruby,Go,Rust,D,HTML/CSS/JS/PHP,MATLAB,Verse(UEFN), Assembler (x64,ARM).
- 東大教員の時に,C++言語で開発した「LLVMコンパイラの拡張」,C言語で開発した独自のリアルタイムOS「Mcube Kernel」をGitHubにオープンソースとして公開.
- 2020年1月~現在はアメリカのノースカロライナ州チャペルヒルにあるGuarantee Happiness LLCのCTOとしてECサイト開発やWeb/SNSマーケティングの業務.2022年6月~現在はアメリカのノースカロライナ州チャペルヒルにあるJapanese Tar Heel, Inc.のCEO兼CTO.
- 最近は自然言語処理AIとイーサリアムに関する有益な情報発信に従事.
- (AI全般を含む)自然言語処理AIの論文の日本語訳や,AIチャットボット(ChatGPT,Auto-GPT,Gemini(旧Bard)など)の記事を50本以上執筆.アメリカのサンフランシスコ(広義のシリコンバレー)の会社でプロンプトエンジニア・マネージャー・Quality Assurance(QA)の業務委託の経験あり.
- (スマートコントラクトのプログラミングを含む)イーサリアムや仮想通貨全般の記事を200本以上執筆.イギリスのロンドンの会社で仮想通貨の英語の記事を日本語に翻訳する業務委託の経験あり.
こういった私から学べます.
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!
C言語のmalloc/calloc/realloc/alloca関数と可変長配列で動的にメモリ確保する方法を紹介します.
目次
malloc関数でメモリ確保
1 2 |
void *malloc(size_t size); void free(void *ptr); |
malloc関数は,ヒープ領域で動的にメモリ確保します.
確保したメモリの内容は初期化されません.
また,メモリを解放する時はfree関数を呼び出します.
malloc関数で動的にメモリ確保,free関数で解放するコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <stdlib.h> int main(void) { int *p; int i, num; printf("Please input a number: "); scanf("%d", &num); if (num <= 0) { fprintf(stderr, "Error: number %d must be positive integer.\n", num); exit(1); } if ((p = (int *) malloc(sizeof(int) * num)) == NULL) { fprintf(stderr, "Error: cannot allocate memory %zu bytes.\n", sizeof(int) * num); exit(2); } for (i = 0; i < num; i++) { p[i] = i; } for (i = 0; i < num; i++) { printf("p[%d] = %d\n", i, p[i]); } free(p); return 0; } |
実行結果は以下になります.
3行目の行末で個数を3と入力したら,int型は4バイトなので,3 * 4 = 12バイト分メモリ確保します.
1 2 3 4 5 6 |
$ gcc malloc.c $ a.out Please input a number: 3 p[0] = 0 p[1] = 1 p[2] = 2 |
calloc関数でメモリ確保
1 |
void *calloc(size_t nmemb, size_t size); |
calloc関数は,ヒープ領域でsizeバイトをnmembの要素数分を割り当てます.
つまり,calloc関数で割り当てるバイトはsize * nmembになります.
malloc関数とは異なり,calloc関数で確保したメモリは0に初期化されます.
calloc関数を利用するコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <stdlib.h> int main(void) { int *p; int i, num; printf("Please input a number: "); scanf("%d", &num); if (num <= 0) { fprintf(stderr, "Error: number %d must be positive integer.\n", num); exit(1); } if ((p = (int *) calloc(num, sizeof(int))) == NULL) { fprintf(stderr, "Error: cannot allocate memory %zu bytes.\n", sizeof(int) * num); exit(2); } for (i = 0; i < num; i++) { p[i] = i; } for (i = 0; i < num; i++) { printf("p[%d] = %d\n", i, p[i]); } free(p); return 0; } |
実行結果は以下になります.
malloc関数と同様です.
1 2 3 4 5 6 |
$ gcc calloc.c $ a.out Please input a number: 3 p[0] = 0 p[1] = 1 p[2] = 2 |
realloc関数でメモリ確保
1 |
void *realloc(void *ptr, size_t size); |
realloc関数は,ポインタptrが示すメモリブロックのサイズをsizeバイトに変更します.
ptrがNULL以外の場合,ptrは以前に呼び出されたmalloc/calloc/realloc関数のいずれかの返り値でなければなりません.
realloc関数を利用するコードは以下になります.
最初にmalloc関数で動的にメモリ確保した後に,realloc関数でメモリを追加します.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <stdlib.h> int main(void) { int *p; int i, num, added_num, total_num; printf("Please input a number: "); scanf("%d", &num); if (num <= 0) { fprintf(stderr, "Error: number %d must be positive integer.\n", num); exit(1); } if ((p = (int *) malloc(sizeof(int) * num)) == NULL) { fprintf(stderr, "Error: cannot allocate memory %zu bytes.\n", sizeof(int) * num); exit(2); } for (i = 0; i < num; i++) { p[i] = i; } for (i = 0; i < num; i++) { printf("p[%d] = %d\n", i, p[i]); } printf("Please input an added number: "); scanf("%d", &added_num); total_num = num + added_num; if ((p = (int *) realloc(p, sizeof(int) * total_num)) == NULL) { fprintf(stderr, "Error: cannot allocate memory %zu bytes.\n", sizeof(int) * total_num); exit(3); } for (i = num; i < total_num; i++) { p[i] = i; } for (i = 0; i < total_num; i++) { printf("p[%d] = %d\n", i, p[i]); } free(p); return 0; } |
実行結果は以下になります.
3行目の行末で個数を3,7行目の行末で追加する個数を2と入力し,合計(3 + 2) * 4 = 40バイト分メモリ確保します.
realloc関数の呼び出し前の配列pの内容(4~6行目)が,呼び出し後も同じであることがわかります(8~10行目).
1 2 3 4 5 6 7 8 9 10 11 12 |
$ gcc realloc.c $ a.out Please input a number: 3 p[0] = 0 p[1] = 1 p[2] = 2 Please input an added number: 2 p[0] = 0 p[1] = 1 p[2] = 2 p[3] = 3 p[4] = 4 |
alloca関数でメモリ確保
alloca関数は,自動的に解放されるメモリを確保します.
malloc/calloc/realloc関数はヒープ領域でメモリ確保するのに対して,alloca関数はスタック領域でメモリ確保します.
一般的には,alloca関数はmalloc/calloc/realloc関数より高速に動作します.
alloca関数は,GCC/Clangで利用できますが,Visual Studioで利用できないことに注意して下さい.
alloca関数を利用するコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <stdlib.h> #include <alloca.h> int main(void) { int *p; int i, num; printf("Please input a number: "); scanf("%d", &num); if (num <= 0) { fprintf(stderr, "Error: number %d must be positive integer.\n", num); exit(1); } p = (int *) alloca(sizeof(int) * num); for (i = 0; i < num; i++) { p[i] = i; } for (i = 0; i < num; i++) { printf("p[%d] = %d\n", i, p[i]); } return 0; } |
実行結果は以下になります.
1 2 3 4 5 6 |
$ gcc alloca.c $ a.out Please input a number: 3 p[0] = 0 p[1] = 1 p[2] = 2 |
可変長配列でメモリ確保
C99規格から導入された可変長配列でメモリ確保します.
alloca関数と同様に可変長配列は,GCC/Clangで利用できますが,Visual Studioで利用できないことに注意して下さい.
可変長配列でメモリ確保するコードは以下になります.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
/* * Author: Hiroyuki Chishiro * License: 2-Clause BSD */ #include <stdio.h> #include <stdlib.h> int main(void) { int i, num; printf("Please input a number: "); scanf("%d", &num); if (num <= 0) { fprintf(stderr, "Error: number %d must be positive integer.\n", num); exit(1); } int p[num]; for (i = 0; i < num; i++) { p[i] = i; } for (i = 0; i < num; i++) { printf("p[%d] = %d\n", i, p[i]); } return 0; } |
実行結果は以下になります.
1 2 3 4 5 6 |
$ gcc vla.c $ a.out Please input a number: 3 p[0] = 0 p[1] = 1 p[2] = 2 |
まとめ
C言語のmalloc/calloc/realloc/alloca関数と可変長配列で動的にメモリ確保する方法を紹介しました.
動的にメモリ確保する方法は便利なので,使いこなしましょう!
C言語を独学で習得することは難しいです.
私にC言語の無料相談をしたいあなたは,公式LINE「ChishiroのC言語」の友だち追加をお願い致します.
私のキャパシティもあり,一定数に達したら終了しますので,今すぐ追加しましょう!
独学が難しいあなたは,元東大教員がおすすめするC言語を学べるオンラインプログラミングスクール5社で自分に合うスクールを見つけましょう.後悔はさせません!