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自体が


free関数により


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


つまり


free関数とは引数に渡されたポインタ変数を


メモリから消去する働きがあります。


もちろん


ポインタ変数pにより


生成される


配列変数

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

のメモリも解放さます。


こうして


解放された

00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

のアドレスのメモリを


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


どうかな? アレサ」


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




























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

作者を応援しよう!

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

応援したユーザー

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