こんにちは、もがちゃんです。
今回は、C言語でmallocでメモリ領域を確保したけどその領域のサイズを変更したい場合に使用するreallocの使い方を簡単なサンプルソースとともに説明します。
目次
reallocの構文
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
reallocの説明
reallocは、ptrが指すメモリ領域を解放し、新しくsizeで指定されたバイトサイズのメモリ領域を確保し、そのポインタを返却します。
古いメモリ領域のサイズが新しいメモリ領域のサイズ以下の場合、古いメモリ領域のサイズ分、新しいメモリ領域にコピーされます。
古いメモリ領域のサイズが新しいメモリ領域のサイズ未満の場合、古いメモリ領域から新しいメモリ領域のサイズ分、新しいメモリ領域にコピーされます。
sizeで指定されたサイズのメモリ領域が確保できない場合は、NULLポインタを返却します。
realloc関数は、ptrが指す古いオブジェクトを解放し、大きさがsizeである新しいオブジェクトへのポインタを返す。新しいオブジェクトの内容は、新しいオブジェクトの大きさと古いオブジェクトの大きさのうち小さい方の大きさまでの部分で、解放する前の古いオブジェクトの内容と同じでなければならない。古いオブジェクトの大きさを超えた部分の新しいオブジェクトのバイトの値は、不定とする。 ptrが空ポインタのとき、realloc関数は、指定された大きさでのmalloc関数と同じ動作をする。それ以外の場合、ptrがcalloc関数、malloc関数若しくはrealloc関数によって以前に返されたポインタと一致しないとき、又は領域がfree関数若しくはrealloc関数の呼出しによって解放されているとき、その動作は、未定義とする。新しいオブジェクトに対する記憶域の割付けができなかった場合、古いオブジェクトは解放されずその値は変化しない。
JISX3010 プログラム言語C
変更したいメモリ領域の先頭アドレスのポインタを指定します。
新しいメモリ領域のサイズをバイトサイズで指定します。
sizeで指定したサイズのメモリ領域確保に
成功した場合、新しく確保したメモリ領域の先頭ポインタを返します。
失敗した場合、NULLポインタを返します。
realloc関数は、新しいオブジェクトへのポインタを返す(古いオブジェクトへのポインタと同じ値かもしれない。)。新しいオブジェクトの割付けができなかった場合、空ポインタを返す。
JISX3010 プログラム言語C
reallocの使い方サンプル
メモリ領域のサイズを小さくした場合、同じ場合、大きくした場合のサンプルを紹介します。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
void *p = NULL;
/*--- サイズを小さく ---*/
p = malloc( (size_t)16 );
if( p == NULL ) {
fprintf( stdout, "malloc error!\n" );
return -1;
}
memset( p, '1', 16 );
fprintf( stdout, "1[%p]===%.16s\n", p, (char*)p );
/* realloc(1) */
p = realloc( p, (size_t)8 );
if( p == NULL ) {
fprintf( stdout, "realloc error!\n" );
return -1;
}
fprintf( stdout, "1[%p]---%.8s\n", p, (char*)p );
free(p);
/*--- サイズを同じに ---*/
p = malloc( (size_t)16 );
if( p == NULL ) {
fprintf( stdout, "malloc error!\n" );
return -1;
}
memset( p, '2', 16 );
fprintf( stdout, "2[%p]===%.16s\n", p, (char*)p );
/* realloc(2) */
p = realloc( p, (size_t)16 );
if( p == NULL ) {
fprintf( stdout, "realloc error!\n" );
return -1;
}
fprintf( stdout, "2[%p]---%.16s\n", p, (char*)p );
free(p);
/*--- サイズを大きく ---*/
p = malloc( (size_t)16 );
if( p == NULL ) {
fprintf( stdout, "malloc error!\n" );
return -1;
}
memset( p, '3', 16 );
fprintf( stdout, "3[%p]===%.16s\n", p, (char*)p );
/* realloc(3) */
p = realloc( p, (size_t)24 );
if( p == NULL ) {
fprintf( stdout, "realloc error!\n" );
return -1;
}
fprintf( stdout, "3[%p]---%.24s\n", p, (char*)p );
free(p);
}

サンプルプログラムの実行結果では、mallocの返却値とreallocの返却値が偶然にも同じアドレスになってました。
この辺りは、メモリの状態や確保するメモリサイズにより変化します。
reallocの使い方まとめ
- reallocを使用する際は、ptrにサイズを変更したいメモリ領域の先頭を指すポインタを指定し、sizeに新しいメモリ領域のサイズをする。
- reallocを使用する際に指定したptrが指すメモリ領域は解放される。
- reallocで確保した新しいメモリ領域には、古いメモリ領域の内容がコピーされる。(新しいメモリ領域のサイズが小さい場合は、新しいメモリ領域のサイズ分)
- reallocで確保したメモリ領域が不要となった場合は、freeで解放する必要がある。
- reallocで新しいサイズのメモリ領域が確保できない場合、NULLポインタが返却される。
- reallocが返却するポインタが指すメモリ領域は、ptrで指定したポインタが指すメモリ領域と同じになるとは限らない。