天国にいけるC言語入門 ヘキサ構造体 ver2.2126
malloc関数によって確保されたメモリをfree関数を使って解放しなければコンピュータは利用できるメモリが減ってしまうためプログラムの実行速度が遅くなることがあります
p = (char *)malloc(sizeof(char)*5);と確保されたメモリに文字列データを格納するにはstrcpy_s(p,5,"neko");のようにstrcpy_s関数を用います
malloc関数によって確保されたメモリをfree関数を使って解放しなければコンピュータは利用できるメモリが減ってしまうためプログラムの実行速度が遅くなることがあります
ソーラー「ふう」
アレサ「ふう」
ソーラー「・・・」
アレサ「・・・」
アレサ「アイスクリームが固まりませんね」
ソーラー「もう1つmalloc関数をつかってメモリを確保する例をみていこうかな?」
アレサ「どのような例題が示されるか楽しみですの😊
malloc関数は興味深い関数ですの」
ソーラー「次のプログラムでは
malloc関数をつかってメモリを確保して
そのメモリに文字列データ"neko"を格納した後
free関数によってそのメモリを解放し
さらに
malloc関数をつかってメモリを確保して
そのメモリに文字列データ"nyao"を格納した後
free関数によってそのメモリを解放しています
さて どのようなコンパイル結果になるかな~」
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *p;
p = (char *)malloc(sizeof(char)*5);
if (p == NULL) {
printf("メモリは確保されませんでした。");
}
else {
printf("メモリは確保されました。\n");
printf("そのメモリのアドレスは %pです。\n", p);
}
printf("%p\n", &p[0]);//ここでp[0]のアドレスをもとめています
printf("%p\n", &p[1]);//ここでp[1]のアドレスをもとめています
printf("%p\n", &p[2]);//ここでp[2]のアドレスをもとめています
printf("%p\n", &p[3]);//ここでp[3]のアドレスをもとめています
printf("%p\n", &p[4]);//ここでp[4]のアドレスをもとめています
p[0]='n';
p[1]='e';
p[2]='k';
p[3]='o';
p[4]='\0';/*ここにナル文字を格納することで確保されたメモリに
文字列データ"neko"をメモリに格納したことになります*/
printf("%c\n", p[0]);
printf("%c\n", p[1]);
printf("%c\n", p[2]);
printf("%c\n", p[3]);
printf("%c\n", p[4]);
printf("%s\n", p);
/*ポインタ変数pを使って
文字列データ"neko"をコマンドプロンプト画面に表示します*/
free(p);
//メモリを解放しました
char *a;
a = (char *)malloc(sizeof(char)*5);
if (a == NULL) {
printf("メモリは確保されませんでした。");
}
else {
printf("メモリは確保されました。\n");
printf("そのメモリのアドレスは %pです。\n", a);
}
printf("%p\n", &a[0]);//ここでa[0]のアドレスをもとめています
printf("%p\n", &a[1]);//ここでa[1]のアドレスをもとめています
printf("%p\n", &a[2]);//ここでa[2]のアドレスをもとめています
printf("%p\n", &a[3]);//ここでa[3]のアドレスをもとめています
printf("%p\n", &a[4]);//ここでa[4]のアドレスをもとめています
a[0]='n';
a[1]='y';
a[2]='a';
a[3]='o';
a[4]='\0';/*ここにナル文字を格納することでポインタ変数aを使って
文字列データ"nyao"をメモリに格納したことになります*/
printf("%c\n", a[0]);
printf("%c\n", a[1]);
printf("%c\n", a[2]);
printf("%c\n", a[3]);
printf("%c\n", a[4]);
printf("%s\n", a);
/*ポインタ変数aを使って
文字列データ"nyao"をコマンドプロンプト画面に表示します*/
free(a);
return 0;
}
ソーラー「コンパイルっ」
コンパイル結果
メモリは確保されました。
そのメモリのアドレスは010D4B40です。
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
n
e
k
o
(空白)
メモリは確保されました。
そのメモリのアドレスは010D4B40です。
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
n
y
a
o
(空白)
アレサ「ソーラーさん 同じアドレスのメモリ
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
がmalloc関数により確保されて
free関数を使って解放されています」
ソーラー「面白いね。
このプログラムでは
malloc関数により確保された先頭のメモリのアドレス010D4B40
が
p = (char *)malloc(sizeof(char)*5);
により
ポインタ変数pに格納されているんだよね。
そうすると
char *pにより作製された
char型の配列変数
p[0]
p[1]
p[2]
p[3]
p[4]
は
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
のアドレス番号の付いたメモリに
アクセスすることができるようになるんだ
free(p);
を実行することにより
それらの動的に確保されたメモリが解放されたあと
a= (char *)malloc(sizeof(char)*5);
が実行されるのですが
またまた
malloc関数により確保された先頭のメモリのアドレス010D4B40
が
a= (char *)malloc(sizeof(char)*5);
の実行により
ポインタ変数aに格納されているね。
そうすると
char *aにより作製された
char型の配列変数
a[0]
a[1]
a[2]
a[3]
a[4]
は
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
のアドレス番号の付いたメモリに
アクセスすることができるようになるんだ
このプログラムでは
malloc関数を使って
確保した
アドレス
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
の付いたメモリに
char *pにより作製された
配列変数
p[0]
p[1]
p[2]
p[3]
p[4]
を使って
p[0]='n';
p[1]='e';
p[2]='k';
p[3]='o';
p[4]='\0';
と
文字列データ"neko"を格納した後
これらの
アドレス番号
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
の付いたメモリを解放しています。
さらにその後
再び
malloc関数を使って
確保した
アドレス
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
の付いたメモリに
char *aにより作製された
配列変数
a[0]
a[1]
a[2]
a[3]
a[4]
を使って
a[0]='n';
a[1]='y';
a[2]='a';
a[3]='o';
a[4]='\0';
と
文字列データ"nyao"を格納した後
これらの
アドレス番号
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
の付いたメモリを解放しています。
アレサ これがmalloc関数の基本的な使い方となっているんだよ。
つまり
このプログラムの目的が
コンパイル結果
メモリは確保されました。
そのメモリのアドレスは010D4B40です。
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
n
e
k
o
(空白)
メモリは確保されました。
そのメモリのアドレスは010D4B40です。
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
n
y
a
o
(空白)
を表示することだったとすると
メモリは確保されました。
そのメモリのアドレスは010D4B40です。
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
n
e
k
o
(空白)
を表示した時点で
アドレス番号
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
の付いたメモリに
文字列データ"neko"を格納している必要はないので
アドレス番号
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
の付いたメモリを
コンピュータが利用できないよう
確保しておく必要はないよね
そこで
free(p);
を実行することにより
アドレス番号
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
の付いたメモリを解放し
アドレス番号
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
の付いたメモリを
コンピュータが利用できるようにしたというわけなんだ
だから
malloc関数により
再び
アドレス番号
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
の付いたメモリを
確保することができ
新たに文字列データ"nyao"を格納できたんだよ。
アドレス番号
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
の付いたメモリの
メモリ解放を行わなくても
もちろん
malloc関数をつかって
アドレス番号
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
の付いたメモリとは
別のメモリを確保することはできるよ
ただし
アドレス番号
010D4B40
010D4B41
010D4B42
010D4B43
010D4B44
の付いたメモリは確保されたままとなるので
プログラムの実行が終了するまで
コンピュータは
それらの5バイト分のデータ容量を持つメモリ
を利用できないってわけだ
次のプログラムをみてよ。
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char *p;
p = (char *)malloc(sizeof(char) * 5);
if (p == NULL) {
printf("メモリは確保されませんでした。");
}
else {
printf("メモリは確保されました。\n");
printf("そのメモリのアドレスは %pです。\n", p);
}
printf("%p\n", &p[0]);//ここでp[0]のアドレスをもとめています
printf("%p\n", &p[1]);//ここでp[1]のアドレスをもとめています
printf("%p\n", &p[2]);//ここでp[2]のアドレスをもとめています
printf("%p\n", &p[3]);//ここでp[3]のアドレスをもとめています
printf("%p\n", &p[4]);//ここでp[4]のアドレスをもとめています
p[0] = 'n';
p[1] = 'e';
p[2] = 'k';
p[3] = 'o';
p[4] = '\0';/*ここにナル文字を格納することでポインタ変数pを使って文字列データ"neko"をメモリに格納したことになります*/
printf("%c\n", p[0]);
printf("%c\n", p[1]);
printf("%c\n", p[2]);
printf("%c\n", p[3]);
printf("%c\n", p[4]);
printf("%s\n", p);
/*ポインタ変数pを使って
文字列データ"neko"をコマンドプロンプト画面に表示します*/
//free(p);を記述してメモリ解放をおこないません👈
char *a;
a = (char *)malloc(sizeof(char) * 5);
if (a == NULL) {
printf("メモリは確保されませんでした。");
}
else {
printf("メモリは確保されました。\n");
printf("そのメモリのアドレスは %pです。\n", a);
}
printf("%p\n", &a[0]);//ここでp[0]のアドレスをもとめています
printf("%p\n", &a[1]);//ここでp[1]のアドレスをもとめています
printf("%p\n", &a[2]);//ここでp[2]のアドレスをもとめています
printf("%p\n", &a[3]);//ここでp[3]のアドレスをもとめています
printf("%p\n", &a[4]);//ここでp[4]のアドレスをもとめています
a[0] = 'n';
a[1] = 'y';
a[2] = 'a';
a[3] = 'o';
a[4] = '\0';/*ここにナル文字を格納することでポインタ変数aを使って文字列データ"nyao"をメモリに格納したことになります*/
printf("%c\n", a[0]);
printf("%c\n", a[1]);
printf("%c\n", a[2]);
printf("%c\n", a[3]);
printf("%c\n", a[4]);
printf("%s\n", a);
/*ポインタ変数aを使って
文字列データ"nyao"をコマンドプロンプト画面に表示します*/
free(a);
return 0;
}
コンパイル結果
メモリは確保されました。
そのメモリのアドレスは01634B40です。
01634B40
01634B41
01634B42
01634B43
01634B44
n
e
k
o
(空白)
メモリは確保されました。
そのメモリのアドレスは01634B78です。
01634B78
01634B79
01634B7A
01634B7B
01634B7C
n
y
a
o
(空白)
(メモリの使用状況によって取得するアドレスの値は変化していきます)
ソーラー「このプログラムでは
p= (char *)malloc(sizeof(char) * 5);
が実行されたとき
malloc関数は
01634B40
01634B41
01634B42
01634B43
01634B44
のアドレス番号の付いたメモリを確保しています。
その後
01634B40
01634B41
01634B42
01634B43
01634B44
のアドレス番号の付いたメモリの
メモリ解放を行わなかったので
a = (char *)malloc(sizeof(char) * 5);
が実行されたとき
malloc関数は
01634B40
01634B41
01634B42
01634B43
01634B44
のアドレス番号の付いたメモリとは
別のメモリ
01634B78
01634B79
01634B7A
01634B7B
01634B7C
を確保しているんだ。
そして
printf("%p\n", &p[0]);
printf("%p\n", &p[1]);
printf("%p\n", &p[2]);
printf("%p\n", &p[3]);
printf("%p\n", &p[4]);
printf("%c\n", p[0]);
printf("%c\n", p[1]);
printf("%c\n", p[2]);
printf("%c\n", p[3]);
printf("%c\n", p[4]);
printf("%s\n", p);
が実行されて
コンパイル結果
メモリは確保されました。
そのメモリのアドレスは01634B40です。
01634B40
01634B41
01634B42
01634B43
01634B44
n
e
k
o
が表示された時点で
アドレス番号
01634B40
01634B41
01634B42
01634B43
01634B44
の付いたメモリを確保しておく必要はないのだけど
free関数を使ってメモリ解放を行わなければ
アドレス番号
01634B40
01634B41
01634B42
01634B43
01634B44
の付いたメモリは
プログラムの実行が終了するまで
確保され続けることになります。
つまり
コンピュータは
プログラムの実行が終了するまで
アドレス番号
01634B40
01634B41
01634B42
01634B43
01634B44
の付いたメモリを
利用できないことになるんだ。
このように
もう使用しないのに
メモリを確保したままにしておくと
5バイト分のメモリなら影響はないのですが
積み重なって
何百バイト、何ギガバイトになってくると
コンピュータは利用できるメモリが少なくなり
プログラムの実行速度が遅くなったり
場合によっては
プログラムを実行できなくなります。
そこで
malloc関数を使って
メモリを確保した後
必要がなければ
free関数を使ってメモリの解放を
行うというわけです。」
アレサ「とっても優れたシステムなんですの(´▽`*)」
ソーラー「free関数を使ってメモリの解放すると
プログラムの実行速度を下げないようにできるんだね。
いろんなソフトで使われてそうだね。」
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます