C 言語で配列を動的に割り当てる
-
関数
malloc
を使って C 言語で配列を動的に割り当てる -
関数
realloc
を用いて C 言語で既に割り当てられたメモリ領域を変更する - C 言語で与えられたオブジェクトの配列に対する割り当てを実装する
この記事では、C 言語で配列を動的に割り当てる方法の複数の方法を示します。
関数 malloc
を使って C 言語で配列を動的に割り当てる
関数 malloc
はヒープ上の動的メモリを確保するためのコア関数です。与えられたバイト数を確保し、メモリ領域へのポインタを返します。したがって、特定のオブジェクト型の配列を動的に確保したい場合は、まずその型へのポインタを宣言しなければならません。次に、引数にオブジェクトのサイズを掛けた要素数を渡して malloc
を呼び出します。
次の例では、文字列を格納するためのメモリを確保しています。セキュアコーディング標準で要求されているように errno
に 0 を設定し、malloc
コールから返されたポインタをチェックして関数の実行が正常に行われたかどうかを確認します。最後に、memove
関数を用いて文字列を確保したメモリにコピーします。
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
const char *str = "random string to be moved";
int main() {
char *arr = NULL;
errno = 0;
arr = malloc(SIZE * sizeof(char));
if (!arr) {
perror("malloc");
exit(EXIT_FAILURE);
}
memmove(arr, str, strlen(str));
printf("arr: %s\n", arr);
free(arr);
exit(EXIT_SUCCESS);
}
出力:
arr: random string to be moved
関数 realloc
を用いて C 言語で既に割り当てられたメモリ領域を変更する
関数 realloc
は、malloc
コールで以前に割り当てられたメモリ領域のサイズを変更するために使用されます。この関数は元のメモリアドレスと新しいサイズを第 2 引数に取ります。realloc
は、要求されたサイズと指定されたアドレス以降の利用可能なメモリに応じて、渡されたものと同じポインタを返すこともあれば、異なるポインタを返すこともあることに注意してください。一方、前の配列の内容は、新たに指定されたサイズまで変更されません。
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
const char *str = "random string to be moved";
int main() {
char *arr = NULL;
errno = 0;
arr = malloc(SIZE);
if (!arr) {
perror("malloc");
exit(EXIT_FAILURE);
}
int num = 102; // User Provided Value
for (int i = 0; i < num; ++i) {
if (i > SIZE) {
arr = realloc(arr, 2 * SIZE);
if (!arr) {
perror("realloc");
exit(EXIT_FAILURE);
}
}
arr[i] = 'a';
}
free(arr);
exit(EXIT_SUCCESS);
}
C 言語で与えられたオブジェクトの配列に対する割り当てを実装する
通常、malloc
はユーザ定義の構造体の配列を確保するために用いられます。malloc
は void
ポインタを返し、暗黙的に他の型にキャストすることができるので、返されたポインタを対応する型に明示的にキャストするのが良い方法です。見落としがちなことや適切な記法が含まれていないことが比較的容易なので、配列の要素数とオブジェクトの型を取得して、適切なキャストを含めて正しい malloc
文を自動的に構築するマクロ式を実装しました。
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
typedef enum {
Jan,
Feb,
MAR,
APR,
MAY,
JUN,
JUL,
AUG,
SEP,
OCT,
NOV,
DEC
} month;
typedef struct {
unsigned char dd;
month mm;
unsigned yy;
} date;
#define MALLOC_ARRAY(number, type) ((type *)malloc((number) * sizeof(type)))
int main() {
date *d = NULL;
errno = 0;
d = MALLOC_ARRAY(SIZE, date);
if (!d) {
perror("malloc");
exit(EXIT_FAILURE);
}
free(d);
exit(EXIT_SUCCESS);
}