11_高度なプログラミング2.md
メモリの動的確保
malloc関数
- メモリを取得する
- 関数が失敗した場合、
NULL
が返ってくる。
- 例) int型1個分の領域を確保する場合
int *pi;
pi = (int *)malloc(sizeof(int));
- 取得した場合、free関数で解放を行う必要がある。
void *malloc(
size_t size
);
free関数
void free(
void *memlock
);
memlock
には、開放するメモリブロックを指定する。
perror関数
void perror(
const char *string
);
- 重要なエラーなどを画面上に出力したい場合に使用する。
サンプルプログラム
#include <stdio.h>
#include <stdlib.h>
int main(){
int *pi, no, i;
printf("いくつの整数値を入力しますか?--");
scanf_s("%d", &no);
pi = (int *)malloc(sizeof(int) *no);
if (pi == NULL){
perror("メモリの確保に失敗しました。");
return -1;
}
for (i = 0; i < no; i++){
printf("%d個目のデータ---", i + 1);
scanf_s("%d", pi + i);
}
printf("入力されたデータは次の通り\n");
for (i = 0; i < no; i++){
printf("No.%d = %d\n", i + 1, *(pi + i));
}
free(pi);
return 0;
}
出力結果
いくつの整数値を入力しますか?--5
1個目のデータ---1
2個目のデータ---2
3個目のデータ---3
4個目のデータ---4
5個目のデータ---5
入力されたデータは次の通り
No.1 = 1
No.2 = 2
No.3 = 3
No.4 = 4
No.5 = 5
calloc関数
- メモリ配列を確保し、0で初期化する。
- 関数が失敗した場合、
NULL
が返ってくる。
- 例) int型のメモリ配列を5個確保する場合
int *pi;
pi = (int *)calloc(5, sizeof(int));
- 取得した場合、free関数で解放を行う必要がある。
void *calloc(
size_t size
);
サンプルコード2
#include <stdio.h>
#include <malloc.h>
#include <string.h>
int main(){
char *pc;
pc = (char*)calloc(16, sizeof(char));
if (pc == NULL){
perror("メモリの確保に失敗しました。");
return -1;
}
strcpy_s(pc,16, "あいうえお");
printf("%s\n", pc);
free(pc);
return 0;
}
出力結果
あいうえお
確保領域の大きさを変更する
realloc関数
void *realloc(
void *memlock,
size_t size
);
サンプルコード
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
int main(){
double *pd, *pd2, sum = 0;
int no = 0, i;
char szData[32];
pd = (double *)malloc(0);
if (pd == NULL){
perror("領域確保に失敗\n");
exit(-1);
}
while (1){
printf("数値を入力してください。(Eで終了): ");
gets_s(szData);
if (strcmp(szData, "E") == 0 || strcmp(szData, "e")==0){
printf("入力を終了します。\n");
break;
}
pd2 = (double *)realloc(pd, sizeof(double) * (no + 1));
if (pd2 == NULL){
perror("領域のサイズ変更に失敗しました。\n");
free(pd); /*すでに確保してあるメモリを解放*/
exit(-2);
}
pd = pd2;
pd[no] = atof(szData);
sum += pd[no];
no++;
}
if (no){
for (i = 0; i < no; i++){
printf("No.%d %f\n", i + 1, pd[i]);
}
printf("合計\t%f\n", sum);
printf("平均\t%f\n", sum/no);
}
free(pd);
return 0;
}
出力結果
数値を入力してください。(Eで終了): 10
数値を入力してください。(Eで終了): 20
数値を入力してください。(Eで終了): 30
数値を入力してください。(Eで終了): e
入力を終了します。
No.1 10.000000
No.2 20.000000
No.3 30.000000
合計 60.000000
平均 20.000000
pd
に0のメモリ配列を確保
- whileが通るたびに
pd2
のメモリ配列を拡張
pd2
の拡張に成功した場合、pd
にpd2
を代入。
pd = (double*)realloc(...)
とした場合、拡張に失敗するとpdにNULL
が代入されるため
確保してある領域に対してfree関数が無効になってしまう。