char*型のポインタ変数pにアドレスが代入されると配列変数p[0]のアドレスはそのアドレスとなりp[1]のアドレスはそのアドレスにchar型のデータ容量1バイトに対応する1を足したものになります

ソーラー「さてさて アレサ 今日もすすんでみようかな」


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


#include <stdio.h>

#include <stdlib.h>


int main(void) {


char *p ;


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


if (p == NULL) {

printf("メモリは確保されませんでした。");

}


else {

printf("メモリは確保されました。\n");

  printf("そのメモリのアドレスは %pです。\n", p);

}


free(p);


return 0;

}


コンパイル結果


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

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



ソーラー「


char *p ;


が実行されるので


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



p= (int *)malloc(sizeof(char)*100);


と記述することはできないと分かったところで


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


が実行されると


一体何がコンピュータによって実行されるかということだよね。


malloc関数の引数に確保したいメモリのバイト数が渡されると


そのバイト数分だけメモリを確保することができます。


実は


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


でなく


p= (char *)malloc(100);


と記述してかまいません。


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


の方がかっこいいかな?


ようは


malloc関数の引数には


確保したいメモリのバイト数(数値)を記述すればいいんだ。


ところでこの確保するという意味がわからないよね。


だって


例えば


scanf関数を使って文字列データの入力を受け付けるときに


普通に


char型の配列宣言


char hairetu[100];


を実行すれば


100バイト分のメモリを確保できるからね。


では一体malloc関数は何をしようとしているのか?



ここで


p= (char *)malloc(sizeof(char)*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]);

printf("%p\n", &p[1]);

printf("%p\n", &p[2]);

printf("%p\n", &p[3]);

printf("%p\n", &p[4]);


free(p);


return 0;

}


コンパイル結果


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

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

00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

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


ソーラー「


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


が実行されると


例えば

00E64B40

00E64B41

00E64B42

00E64B43

00E64B44

のアドレスを持つ

5バイト分のメモリが確保されることになります。


malloc(sizeof(char)*5)は


確保したメモリの先頭のアドレス00E64B40を戻り値として


もっているんですね。どうかな アレサ


わっかりやす~いかな😊」


アレサ「とても わかりやすいですの」


ソーラー「そして


そのアドレス00E64B40がポインタ変数pに格納されることになります。


すると


なんと


ポインタ変数pにより作製される5個の配列変数


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


のアドレスをもつことになるんだ。


わおう


おどろきだね。



そのことが


今さっきのプログラムで示されていたってわけさ。


#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🍓を格納したから


&p[0]

&p[1]

&p[2]

&p[3]

&p[4]

はそれぞれ


00E64B40

00E64B41

00E64B42

00E64B43

00E64B44


のアドレスとなったわけではないんだ


このことはポインタ変数の一般的な性質で


アドレス00E64B40が


malloc関数の戻り値であるアドレスでなかったとしても


ポインタ変数pにアドレス00E64B40が代入されると


ポインタ変数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


のアドレスをもつことになります。


そのことを次のプログラムで確認してみようかな?


#include <stdio.h>


int main(void) {

char *p;

char a='b';


printf("%p\n",&a);


p=&a;


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


return 0;

}


コンパイル結果

00B7FE73

00B7FE73

00B7FE74

00B7FE75

00B7FE76

00B7FE77


ソーラー「このプログラムでは


ポインタ変数pに


char型の変数aのアドレス00B7FE73が代入されると


p[0]

p[1]

p[2]

p[3]

p[4]


のアドレスである


&p[0]

&p[1]

&p[2]

&p[3]

&p[4]



00B7FE73

00B7FE74

00B7FE75

00B7FE76

00B7FE77


となることが示されています。」



アレサ「順調ですの。 ソーラーさん」


ソーラー「へへ


ところで


malloc関数をつかっても


必ずしもメモリを確保できるとはかぎりません。


確保できるだけの容量がないかもしれないからね。


malloc関数をつかってメモリを確保できない場合


malloc関数には戻り値としてNULLが


返されることになります。


すると


プログラムの中の


if (p == NULL) {

printf("メモリは確保されませんでした。");

}


else {

printf("メモリは確保されました。\n");

printf("そのメモリのアドレスは %pです。\n", p);

}



if (p == NULL) {

printf("メモリは確保されませんでした。");

}


が実行されて


コンパイル結果


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


がコマンドプロンプト画面に表示されることになるんだよ。」

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

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

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

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

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