malloc関数を使って確保されたメモリに文字列データを格納するには🌞必ず🌞strcpy関数を使用する必要があります

malloc関数によって確保されたメモリにデータを入力しfree関数によってメモリ解放を行ってみます その1

ソーラー「今のプログラムでは→


#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


ソーラー「→malloc関数を使って


00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

のアドレスをもつメモリを


コンピュータが利用できないよう確保し


free関数を使って


それらのメモリを


コンピュータが利用できるよう解放しました。」


ソーラー「しかし


malloc関数をつかって


メモリを確保して


free関数で


メモリを解放しただけでは


malloc関数が何のためにあるのかよく分からないよね


一体このmalloc関数はどのようなときにプログラムで用いられるのか


気になるんじゃないかな


そこで今度は


malloc関数を用いるとどのような点が便利なのかプログラムを


構成して確かめてみよ~うじゃないか~」



アレサ「はいっ😊先程のプログラムをご用意いたします。

👇

#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

00E64B41

00E64B42

00E64B43

00E64B44

のアドレスをもつメモリが


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


このことを動的にメモリが確保されたといいます



☆   ☆   ☆   ☆   ☆   ☆   ☆


動的にメモリを確保するということはいつでも


確保されたメモリを解放できるという意味が込められています


確保されたメモリを解放することに関しては詳しくはこれから解説されます


                                           solarplexussより


☆   ☆   ☆   ☆   ☆   ☆   ☆


00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

のアドレスをもつメモリには


ポインタ変数宣言


char *p;


によって作製された

char型の配列変数

p[0]

p[1]

p[2]

p[3]

p[4]


を使ってアクセスすることができます


つまり


char型の配列変数

p[0]

p[1]

p[2]

p[3]

p[4]

に文字データを格納すると


00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

のアドレス番号をもつメモリに


文字データを格納することができるというわけです。


そこで

💖💖💖💖💖💖

char型の配列変数

p[0]

p[1]

p[2]

p[3]

p[4]

をつかって

00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

のアドレス番号をもつメモリに


文字データを格納してから


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';/*ここにナル文字を格納することでポインタ変数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;


}



コンパイル結果


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

そのメモリのアドレスは010D4B40です。

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

n

e

k

o

(空白)

neko



(これらのアドレスの値はメモリの使用状況によってことなってきます。)


ソーラー「このプログラムのポイントは


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


010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

のアドレス番号の付いたメモリに


char型の配列変数

p[0]

p[1]

p[2]

p[3]

p[4]

をつかって


文字列データ"neko"



p[0]='n';

p[1]='e';

p[2]='k';

p[3]='o';

p[4]='\0';


と格納したことにあるんだよ


このとき


コンピュータは


010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

のアドレス番号の付いた5バイト分のメモリを


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


もし


free関数を使ってメモリ解放をおこなわなければ


プログラムの実行が終了するまで


010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

のアドレス番号の付いた5バイト分のメモリを


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


ところで


このプログラムでは


コンパイル結果


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

そのメモリのアドレスは010D4B40です。

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

n

e

k

o

(空白)

neko


が表示されれば


010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

のアドレス番号の付いた5バイト分のメモリを


確保しておく必要はないよね。


つまり


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


が実行されたら


010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

のアドレス番号の付いた5バイト分のメモリを


確保しておく必要はないってわけだ


そこで


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


が実行されたのち


free(p);


を実行して


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

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


char型の配列変数

p[0]

p[1]

p[2]

p[3]

p[4]

に格納されているデータを消去する


つまり


char型の配列変数

p[0]

p[1]

p[2]

p[3]

p[4]

がアクセスしている


010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

のアドレス番号の付いたメモリを


解放してコンピュータが再び利用できるようにしたいってわけなんだよ😊


free(p);


が実行されて


010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

のアドレス番号の付いたメモリが


解放されたなら


コンピュータは


010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

のアドレス番号の付いたメモリを


使用することができることになるんだよ」


アレサ「


char *p;


によって生成されるchar型の配列変数


p[0]

p[1]

p[2]

p[3]

p[4]


をつかって


動的に確保された


010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

のアドレス番号の付いたメモリに文字データを格納できるんですね。


メモリが確保されて


コンピュータはそのメモリを使用できないとはいっても


ユーザーはそのメモリにデータを自由に格納することができるんですね」



ソーラー「今日はここまでにしよっかな


とおもったけど


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


010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

のアドレス番号の付いたメモリに


char型の配列変数

p[0]

p[1]

p[2]

p[3]

p[4]

をつかって


文字列データ"neko"



p[0]='n';

p[1]='e';

p[2]='k';

p[3]='o';

p[4]='\0';


と格納するのは


手間がかかるね。


実は


strcpy_s関数を用いて


strcpy_s(p, 50, "neko");


を実行すれば


簡単に


文字列データ"neko"



p[0]='n';

p[1]='e';

p[2]='k';

p[3]='o';

p[4]='\0';


と格納することができます。


その際


ヘッダファイル<string.h>をインクルードしてください


ヘッダファイル<string.h>をインクルードしなければ


strcpy_s関数


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


そのことを示すプログラムはこちらです😊

👇


#include <stdio.h>

#include <stdlib.h>

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



strcpy_s(p, 50, "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;

}



コンパイル結果


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

そのメモリのアドレスは010D4B40です。

010D4B40

010D4B41

010D4B42

010D4B43

010D4B44

n

e

k

o

(空白)

neko


ソーラー「

p[0]='n';

p[1]='e';

p[2]='k';

p[3]='o';

p[4]='\0';

を実行するより


strcpy_s(p, 50, "neko");


を実行するほうが


簡単だね


p="neko";


を実行したほうが簡単そうに思えるけど


p="neko";


を実行すると警告文が表示されるので注意してくださいね」


アレサ「ソーラーさん


p="neko";


を実行すれば


ポインタ変数pに文字列データ


"neko"


が格納されるのではないですか?」


ソーラー「そこはとっても間違いやすいところなんだ


p="neko";


を実行すれば


ポインタ変数pに文字列データ


"neko"


が格納されるのではなく


p="neko";


を実行すれば


ポインタ変数pを使って


文字列データ"neko"



メモリに格納できるというほうが正しいかな😊」


アレサ「??」













































































































































































































































































































































ソーラーのお洗濯実況中です



ソーラー「実に清々しいな~


こんなに青空が広がっていると気分がいいね。


天気もいいし僕はお洗濯でもしようかな」



ソーラーさん、大分洗濯物がたまっていたようです



アレサ「ソーラーさん 私もお手伝いしましょうか?」


ソーラー「いや そこまでは・・


君には助けてもらってばかりだからね」


アレサ「いえいえ 遠慮なさらずに」


ソーラー「いやあ とりあえず このかんかん照りのお日様で


乾かしてしまおうと思ったんだ」


アレサ「確かに今日はとてもお日様が眩しいです。」


ソーラー「さあてと この洗濯物をどうしようかな」


アレサ「お任せください」


アレサは洗濯ものを受け取ると水を張った桶にさっとひたす


すると


一瞬で汚れが落ちてしまった


驚きの白さだ


すぐさま


アレサが


洗濯ものを物干し竿に干しにかかる。


ソーラー「アレサ どうなってるんだい


洗濯ものがぴかぴかしてるね すごいな~」


アレサ「ソーラーさん 洗濯物がもう乾いていますの」


ソーラー「は、はやい い、いや 暑すぎるんだ」





ソーラー、アレサ「はい、この驚きの白さ


というわけで お洗濯には





       台所洗剤チャレンジ ジョイ!」





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

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

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

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

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