天国にいけるC言語入門 ヘキサ構造体 ver2.2126
p = (char *)malloc(sizeof(char)*5);により確保されたメモリは配列変数p[0] p[1] p[2] p[3] p[4] でアクセスすることができます
🌞動的にメモリを確保するということは🌞 🌞好きなタイミングでメモリをコンピュータが利用できるように解放できる🌞 ということなのです
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
・
・
・
017FE4D9
の
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;
}
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます