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より
新規登録で充実の読書を
- マイページ
- 読書の状況から作品を自動で分類して簡単に管理できる
- 小説の未読話数がひと目でわかり前回の続きから読める
- フォローしたユーザーの活動を追える
- 通知
- 小説の更新や作者の新作の情報を受け取れる
- 閲覧履歴
- 以前読んだ小説が一覧で見つけやすい
アカウントをお持ちの方はログイン
ビューワー設定
文字サイズ
背景色
フォント
組み方向
機能をオンにすると、画面の下部をタップする度に自動的にスクロールして読み進められます。
応援すると応援コメントも書けます