🌞動的にメモリを確保するということは🌞  🌞好きなタイミングでメモリをコンピュータが利用できるように解放できる🌞 ということなのです

p = (char *)malloc(sizeof(char)*5);により確保されたメモリは配列変数p[0] p[1] p[2] p[3] p[4] でアクセスすることができます

ソーラー「アレサ~つぎいってみよ~」


アレサ「はいっ ソーラーさん。」


#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]のアドレスをもとめています


free(p);


//メモリを解放しました


return 0;


}


コンパイル結果


メモリは確保されました。

そのメモリのアドレスは00E64B40です。

00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

(このアドレスの値はご使用の環境によって異なってきます)


ソーラー「


p = (char *)malloc(sizeof(char)*5);


が実行されると

sizeof(char)*5=5

がmalloc関数の引数に記述されているため


00E64B40

00E64B41

00E64B42

00E64B43

00E64B44


のアドレスのメモリ

malloc関数によって動的に確保されることになります。


ポインタ変数pには


(char *)malloc(sizeof(char)*5)


つまり


malloc関数の戻り値であるアドレス00E64B40


が代入されるので


配列変数

p[0]

p[1]

p[2]

p[3]

p[4]

のアドレス


&p[0]

&p[1]

&p[2]

&p[3]

&p[4]


はそれぞれ


先のエピソードでもみてきたように


00E64B40

00E64B41

00E64B42

00E64B43

00E64B44


となります。


配列変数

p[0]

p[1]

p[2]

p[3]

p[4]

アドレス

00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

のメモリに

アクセスしている窓というわけだね。



このとき


配列変数

p[0]

p[1]

p[2]

p[3]

p[4]

がアクセスしているアドレス


00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

のメモリ



malloc関数により動的に確保されています。


メモリが動的に確保されているというのはどういうことかというと


メモリが動的に確保されているとき


コンピュータは


配列変数

p[0]

p[1]

p[2]

p[3]

p[4]

がアクセスしているアドレス

00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

のメモリ

を使用することはできません。


例えば いろいろなソフトを作動させているときに


メモリは使用されますが


コンピュータは


malloc関数によって動的に確保された


配列変数

p[0]

p[1]

p[2]

p[3]

p[4]

がアクセスしている

00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

のメモリ

を使用できないのです。


p = (char *)malloc(sizeof(char)*5);



実行されることにより動的に確保されたメモリは


00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

のアドレスを持つメモリで


容量は5バイト分ですが


p = (char *)malloc(sizeof(char)*1000000);



実行されると動的に確保されるメモリは


00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

0‭17FE4D9‬

1メガバイト分になります


malloc関数を多用することにより


どんどんメモリを動的に確保していくと


コンピュータは利用できるメモリがすくなくなり


ソフトの実行速度が遅くなります。


さらに


malloc関数によりソフトを作動させるためのメモリまで


動的に確保されてしまうと


ソフトを作動させることはできなくなります。


そこで登場するのが


動的に確保されたメモリを解放する


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]のアドレスをもとめています


free(p);


//メモリを解放しました


return 0;


}

コンパイル結果


メモリは確保されました。

そのメモリのアドレスは00E64B40です。

00E64B40

00E64B41

00E64B42

00E64B43

00E64B44


でも

free(p);


free関数が登場していましたね。


free(p);



free関数の引数に


アドレス00E64B40を格納しているポインタ変数pが代入されています。


free関数の引数に


アドレス00E64B40を格納しているポインタ変数pが代入されると


malloc関数によって確保された

アドレス

00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

のメモリは解放されます


いいかえると


ポインタ変数pにより生成される


配列変数

p[0]

p[1]

p[2]

p[3]

p[4]

がアクセスしているメモリが解放されているといえます


free(p);


が実行されると


ポインタ変数p自体は消去されないのですが


ポインタ変数pに格納されているアドレスと


動的に確保されたメモリに格納されているデータは


free関数により


メモリ上から消去されます。


つまり


配列変数

p[0]

p[1]

p[2]

p[3]

p[4]

がアクセスしている

アドレス

00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

のメモリは解放されるというわけです。


こうして


free(p);


の実行により


解放された

00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

のアドレスのメモリを


再びコンピュータは使用することができるようになります。


どうかな? アレサ」


アレサ「絶好調ですの💖 ソーラーさん😊」






おまけ



free(p);


が実行されると


ポインタ変数p自体は消去されないのですが


ポインタ変数pに格納されているアドレスと


動的に確保されたメモリに格納されているデータは


free関数により


メモリ上から消去されます。


つまり


ポインタ変数p自体は消去されていません


ですので


free(p);


を実行してメモリを解放した後


再び


ポインタ変数pを用いて


動的にメモリを確保することができます



そのことを示すプログラムはこちらになります

👇


#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);


//メモリを解放しました




//👇🌞再びポインタ変数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);


return 0;


}























  • Twitterで共有
  • Facebookで共有
  • はてなブックマークでブックマーク

作者を応援しよう!

ハートをクリックで、簡単に応援の気持ちを伝えられます。(ログインが必要です)

応援したユーザー

応援すると応援コメントも書けます

新規登録で充実の読書を

マイページ
読書の状況から作品を自動で分類して簡単に管理できる
小説の未読話数がひと目でわかり前回の続きから読める
フォローしたユーザーの活動を追える
通知
小説の更新や作者の新作の情報を受け取れる
閲覧履歴
以前読んだ小説が一覧で見つけやすい
新規ユーザー登録無料

アカウントをお持ちの方はログイン

カクヨムで可能な読書体験をくわしく知る