malloc関数はアドレスを戻り値としてもちます そのアドレスをポインタ変数に格納するにはアドレスを格納する型にキャストする必要があります

ソーラー「もう1回プログラムをみてみようかな


#pragma warning(disable: 4996)


#include <stdio.h>


int main(void){


char hairetu[100];


scanf("%s",hairetu);


printf("%s\n",hairetu);


char str[100];


scanf("%s",str);


printf("%s\n",str);


return 0;


}


コンパイル結果


(Visual Studioの場合)

(EAZY IDECの場合)


neko(と入力すると)

neko

nyaonyao(と入力すると)

nyaonyao


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


コマンドプロンプト画面から入力された


文字列nekoを


char型のhairetuに格納し


printf("%s\n",hairetu);


を用いて


文字列nekoをコマンドプロンプト画面に表示しています


その時点でもうすでに


char型(1バイト)×100個=100バイトのメモリを


確保している必要はありませんが


char hairetu[100];


により確保された100バイトのメモリは


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


確保され続け


その間は


その100バイトのメモリは


コンピュータは使用することができません。



そこでもう


nekoとコマンドプロンプト画面に表示したので


char hairetu[100];


により確保された100バイトのメモリを


コンピュータが使用できるようにしたいというわけなんだ。


メモリを解放してあげるわけなんだね。


こまめにメモリを解放しておけば


コンピュータがフリーズする可能性も少なくなるというわけなんだね。


そこで登場するのがmalloc関数とfree関数なんだ



まあ 次のプログラムをみてよ。


#include <stdio.h>

#include <stdlib.h>


int main(void) {


char* p ;


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


if (p == NULL) {

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

}


else {

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

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

}


free(p);


return 0;

}


コンパイル結果


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

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


ソーラー「ふふ ぜんぜん 意味が分からないんだ😊


          そこが また  いいところなんだ」



アレサ「これはどのようなことを行っているプログラムなのですか?」



ソーラー「まず


#include <stdlib.h>


に注目だね。


malloc関数はヘッダファイル<stdlib.h>を


インクルードしないとつかえないんだ。



そして


char* p ;


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


の意味だね。


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



sizeof(char)*100は確保したいメモリのバイト数100を表しています


sizeof(char)に100がかけあわされているってわけだね


ここで


sizeof(char)は何かということですね


sizeof演算子とは


変数の型が何バイトの格納容量を持つかを


示すことができます


char型は1バイトのデータ格納容量をもつので


sizeof(char)は1


をあらわします


int型は4バイトのデータ格納容量をもつので


sizeof(int)は4


をあらわします


float型は4バイトのデータ格納容量をもつので


sizeof(float)は4


をあらわします


float型は8バイトのデータ格納容量をもつので


sizeof(double)は8を表します


そのプログラムはこちらです

👇


#include <stdio.h>

#include <stdlib.h>//🌞malloc関数後に登場するfree関数を使用するときはヘッダファイル<stdlib.h>をインクルードしてください


int main(void) {


printf("sizeof(char)は%dバイトです\n", sizeof(char));

printf("確保されたメモリは%dバイトです\n", sizeof(char) * 100);


printf("sizeof(int)は%dバイトです\n", sizeof(int));

printf("確保されたメモリは%dバイトです\n", sizeof(int) * 100);


printf("sizeof(float)は%dバイトです\n", sizeof(float));

printf("確保されたメモリは%dバイトです\n", sizeof(float) * 100);


printf("sizeof(double)は%dバイトです\n", sizeof(double));

printf("確保されたメモリは%dバイトです\n", sizeof(double) * 100);


return 0;

}


ビルド実行結果


sizeof(char)は1バイトです

確保されたメモリは100バイトです

sizeof(int)は4バイトです

確保されたメモリは400バイトです

sizeof(float)は4バイトです

確保されたメモリは400バイトです

sizeof(double)は8バイトです

確保されたメモリは800バイトです



ソーラー「このように


char型は1バイトのデータ格納容量をもちます


ですので


それを100倍した


(char)かける100である


(char)*100は


100バイトのデータ格納容量を持つことになり


sizeof(char)*100 は100をあらわします。


ここでの注目ポイントは




🌞sizeof(char)は純粋にただの数値データ1を表しているという点です🌞


つまり


sizeof(char)=1

というわけです


       sizeof(char)には



charが記述されているからと言って何かの特別な意味はありません


同様に


🌞sizeof(int)は純粋にただの数値データ4を表しています🌞


つまり


sizeof(char)=4

というわけです


       sizeof(int)には



intが記述されているからと言って何か特別な意味はありません



ですので


char* p ;


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



sizeof(char)*100を


100


に置き換えて


char* p ;


p= (char*)malloc(100);


と記述することができるんです





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

p= (char*)malloc(100);


の実行において


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


100バイト分のメモリを確保することになります


例えば

00D94B40

00D94B41

00D94B42

00D94B43

00D94B44

00D94B45

00D94B46

00D94B47

00D94BA2

00D94BA3

のアドレスをもつ100バイト分のメモリが


malloc(sizeof(char)*100);


の実行により


確保されます。


そのとき


確保した100バイトのメモリの


先頭のアドレス


00D94B40をmalloc関数は戻り値として持つことになります



ただし このとき


このアドレス00D94B40は


char*型に格納されるアドレスなのか?


int*型に格納されるアドレスなのか?


確定していません


char* p ;


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


を実行して


char型の変数のアドレスを格納することのできる


キャラアスタリスク型char*のポインタ変数pを作製したなら


このアドレス00D94B40を


キャラアスタリスク型char*に格納する必要があります


そうしなければ


アドレス00D94B40



キャラアスタリスク型char*のポインタ変数p


に代入することはできません


そこで


malloc(sizeof(char)*100)をchar*のポインタ変数pに格納するために


malloc(sizeof(char)*100)に


(char*)


がくっつけられることになります



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


にはそのような意味があるんですね


(char*)の()はキャスト演算子で


(char*)は作用することができるアドレスを


キャラアスタリスク型char*に格納し直すはたらきがあります」



🌞    🌞    🌞    🌞    🌞 


この部分については


非常に詳しい解説が本書の


int*型のポインタ変数はint型の変数のアドレス,char*型のポインタ変数はint型の変数のアドレス, void* 型のポインタ変数はすべての型の変数のアドレスを格納することができます


のエピソード



void*型の変数のポインタ演算を行うことはできません


のエピソード



void*型のポインタ変数dを他のint*型やdouble型にキャストしてみよう


のエピソード



で解説されています


🌞    🌞    🌞    🌞    🌞



アレサ「


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


はそのような仕組みになっていたのですね


1歩前進です💖」」



ソーラー「そうなんだよ。


いやあ


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


という表現は


僕も気になっていたんだ~


ポインタ変数pにアドレスを格納するなら


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


でなく


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


でもよさそうですよね。


どう思うかな。 みなさん」


アレサ「malloc(sizeof(char)*100)はアドレス00D94B40を戻り値として


もつのでそう思う方もおおいとおもわれますの」


ソーラー「


ここがおもしろいところだよね。


アドレス00D94B40が


キャラアスタリスク型char *でメモリに格納されているのか?


イントアスタリスク型int *でメモリに格納されているのか?


ということをコンピュータに理解させるために


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


のように


(char*)を用いる必要があるんだね


最初


malloc(sizeof(char)*100)


をみたとき


(sizeof(char)*100)


とcharが記述されていたので


char型のメモリが100個分確保されるので


malloc関数に戻される戻り値はchar*型に格納されるとおもっていたんだよ


でも


sizeof(char)はただの数値データ1であり


malloc(sizeof(char)*100)



malloc(100)に等しく


malloc(100)は


単に


100バイト分のメモリが確保されるという意味だったんだね


malloc(100)に戻される戻り値は


sizeof(char)のcharによって


char*型に格納されるというようなことはないってわけだったんだね



だから

sizeof(char)*100

sizeof(int)*25


ともに


100を表すので



malloc(100)

malloc(sizeof(char)*100)

malloc(sizeof(int)*100)


は全部等しい命令文となり


p= (char*)malloc(100);

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

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


もすべて等しい命令文となります


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



charとintが混ざっているところが楽しいね(^_-)-☆


ところで


イントアスタリスク型int*もアドレスを格納するがことができる型ですが


それは次のエピソードで説明と行こうかな😊」



🌞    🌞    🌞


このとき


キャラアスタリスク型char*にキャスト演算子()を用いて


アドレス00D94B40を格納することを


キャラアスタリスク型char*にアドレス00D94B40を



          🍋キャスト🍋


するといいます。


キャストとは英語で搭載するという意味です。


天国にいけるC言語入門


https://kakuyomu.jp/works/1177354054881541562/episodes/1177354054884520154


のエピソードでもキャスト演算子は登場しましたね。



#include <stdio.h>


int main(void){


float a;

a=1.5;


printf("あなたの預金額はただいま%d円です。\n",(int )(10000*a));

/*ここでキャスト演算子( )をもちいることにより実数値である(10000*a)をint型にキャストしています*/



return 0;


}


コンパイル結果


あなたの預金額はただいま15000円です。


(統合開発環境EAZY IDECの場合)


あなたの預金額はただいま15000円です。


printf("あなたの預金額はただいま%d円です。\n",(int )(10000*a));


と記述していたのを


(int)を用いず


printf("あなたの預金額はただいま%d円です。\n",(10000*a));


と記述してしまうと


%d出力変換指定子を用いて実数値である10000*aをprintf出力表示することになり


コンパイル結果


あなたの預金額はただいま15000円です。


を表示することはできません


次のプログラムは次のようになります

👇

#include <stdio.h>


int main(void) {


float a;

a = 1.5;


printf("あなたの預金額はただいま%d円です。\n", (10000 * a));

/*ここではキャスト演算子( )をもちいず実数値である(10000*a)をint型にキャストしていません*/



return 0;


}


コンパイル結果


あなたの預金額はただいま0円です。


(int)を用いて実数値である(10000*a)をint型に格納して


整数値15000にしておく必要があるのですね


このようにキャスト演算子()


は望みの型にデータを格納するために用いられます


               

                solarplexussより




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

作者を応援しよう!

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

応援したユーザー

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

新規登録で充実の読書を

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

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

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