こんにちは､ そしてお帰りなさい｡ 今回の講義では､ 前回の課題であったmallocを使った動的なメモリ確保を理解してもらうためのデモを行いたいと思います｡
キーボードから文字列を読み取って表示するという単純なものですが､
動的に割り当てられたポインタ､ キャラクタ・ポインタを使用します｡
それでは､ コードブロックを持ち出して､ 新しいプロジェクトを作りましょう｡
そして､ この1つの動的メモリ割り当ての例と名付けることにします｡
そして､ 動的メモリ割り当てを利用する際にまず必要なことは､
標準の lib をインクルードしておくことです｡
幸いなことに､ コードブロックのプロジェクトを作成すると､
自動的にそれを含めることができます｡
しかし､ standard libを入れる必要があるのは､ malloc､ つまりmalloc関数がそこに入っているからです｡
そして､
mallocは､ メモリを確保するためのメイン関数であることを忘れてはならない｡ callocもありますね｡
callocは本当に重要です｡ なぜなら､
callocは2つのパラメータで何バイト必要かを計算してくれるからです｡
しかし､ callocの本当に良いところは､ データがint型であればすべて0に初期化されるなど､
本当に素晴らしい機能です｡
reallocがあるじゃないですか｡ Reallocは､ すでに割り当てられたメモリを拡張します｡
だから､ ポインターで渡すのです｡
そのポインタから､ そのために割り当てられているメモリの量を判断し､
そこにあったものをすべて新しいメモリ位置にコピーします｡ さらに､
あと何バイト割り当てたいかを指定すると､ それを新しいメモリ位置に追加してくれます｡
本当に素晴らしい機能です｡
しかし､ mallocを使って整数のメモリを確保する場合､ バイト単位でメモリを確保することを決めなければならないが､
通常はsizeof演算子を使いたいことを覚えておいてほしい｡
ではここで､ それをご紹介しましょう｡
メインメソッドで､ 整数を作成し､ それをサイズとします｡
は､
実行時に何バイト確保したいかを入力するので､ そのサイズを格納することになります｡
もうひとつは､ charポインタを作成し､ これは単にテキストにするつもりです｡
そして､
これは最初から何も指していないので､ nullに初期化するつもりです｡
まず最初に､ ユーザーにサイズの入力を求めたいと思います｡
だから､ printfと言うのは､
テキストの制限を入力するんだ｡
そして､ 何バイトの文字数を割り当てるかを入力することになる｡
そして､ それをscanfで読み込む｡
Scanfの場合､ 最初のパラメータはデータの型を表すフォーマット指定子の型である｡
これは整数を読んでいるので､ パーセントdになります｡
それから､ scanfはポインタを取ることを忘れないでください｡
ポインターを取る関数では､ 渡すためのアドレスが必要なことがわかりました｡
だから､ sizeを渡すにしても､ 演算子のアドレスを使わないとsizeはアドレスにならない｡
だから､ アンパサンドで､ サイズと言って､
バイト数を読み込むんだ｡
バイト数が決まれば､ あとはmalloc関数でメモリを確保すればいい｡
そしてmallocはvoidポインタを返そうとします｡
そして､ そのポインタは､ 新しく割り当てられたメモリの先頭アドレスになるのです｡
だから､ テキストにそのまま割り当てることができる｡
なぜなら､ テキストはポインターであることを忘れてはならないからです｡
返された新しいアドレスにテキストを当てたいのです｡
mallocはvoidポインタを返すので､ それをキャストする必要があります｡
指し示すデータの種類は文字なので､ char starとしたいところですが､ malloc関数を呼び出すことができます｡
malloc関数は､ バイト数を受け取ります｡
それで､ バイト数を渡しただけでは､ そのバイト数だけしか割り当てられないんです｡
しかし､
データの種類によっては､ 2バイトや4バイトになることもある｡
つまり､ 10文字を割り当てたかったら､
10文字×charのサイズになるようにしたいのです｡
そこで今度は､ sizeofのn倍ということになります｡
sizeof演算子はマシンに依存しないので､
malloc関数でよく使われ､ 実際に割り当てる必要がある量を教えてくれます｡
さて､ これは整数がある場合に､ より関連性が高くなります｡ 整数は､ 使っているシステムやアーキテクチャによって､
4バイト､ 2バイト､ 普通は2バイトか4バイトで表現されることを覚えておいてください｡
1つの整数を格納したいから4バイトのメモリを作ろう､
と言っても､ 2バイトだったらどうするんだ､ ということになりかねない｡
ですから､ 常に何個の整数または何個の文字を作りたいかを行い､
それに自分のシステムでの文字の大きさを掛け合わせるようにしたいのです｡
Sizeof
演算子は､ char が占めるバイト数を表示します｡ つまり､ 10個の文字列を作りたい場合は､
文字列の大きさの10倍と言うわけです｡ 10個の整数を格納するために10個の整数を作る場合､
intのサイズの10倍と言いますが､
これは本当に重要なことです｡
calloc関数を使えば､ そんなことをする必要はない｡ Callocは実際には2つのパラメータを取ります｡
そして､
最初のパラメーターはポインターだと思います｡ そして､
2番目のパラメーターはバイトのサイズです｡
つまり､ 24個のintを渡すと､ 自動的に24個のintが割り当てられます｡
だからcallocは､ この掛け算をする必要がないので､ 本当にいいツールだと思います｡
つまり､ callocの場合､ 最初のパラメータはサイズである｡
つまり､ 10個のintを作りたい場合は､ 10を渡すだけでいいのです｡
そして､ 2番目のパラメータは､
バイトのサイズです｡ だから､ 掛け算はしなくていいんです｡ ちょっとだけ手間を省くことができます｡
メモリを割り当てたので､ textの参照を解除しようとする前に､
textがNULLでないことを確認したい｡
つまり､ not textで囲むと､ nullでないことを示すことになります｡
また､ 明示的にif text is not equal to nullとすることもできます｡
ポインターの参照を解除しようとすると､ とてもとても危険なので､
いつもそうしたいのです｡
何が起こるかわからない｡ データを書き込むことができるかもしれません｡
を入れました｡ メモリの別の場所に書き込んでしまうのだ｡ だから､ プログラムがめちゃくちゃになったり､
セグメンテーションフォールトが発生してプログラムがクラッシュする可能性がある｡
しかし､ 本当にそのメモリを確保しさえすれば､ 実際にデータを読み込むことができるようになったのです｡
ここではgit sを使うこともできますし､ scanfを使うこともできます｡
しかし､ あなたがやりたいことは､
プリントアウトしてテキストを入力し､
読みやすいようにここに改行も加えたいのです｡
そして､ 私たちが慣れ親しんでいるscanfを使うことにします｡
そしてscanfはパーセントで読み込むだけです｡
実は､ あるコツを教えてあげるんです｡
scanfで次の文字を読み込むので一時停止し､
get sでテキストを読み込んでいます｡
また､ getsは通常f getsを使用することができる別の関数です｡ 入力ストリームにセットすればいいのです｡
しかし､ getsは標準入力ストリームから読み込もうとしている｡ デフォルトではキーボードである｡
そして､ getはポインターを取ることになる｡ つまり､ すでにポインタなのでテキストを渡すだけでよく､
演算子のアドレスを入れる必要はないのです｡
また､ get askの良いところは､ スペースで区切られた複数の文字列を読み込むことができる点です｡
実際にgetで読んだら､ プリントアウトすればいいだけです｡
つまり､
inputtedがワードパーセントsバックスラッシュnで､ 次にカンマテキストであればinputed
textと言うことができます｡ テキストはポインターです｡
Printfはポインターを受け取ります｡ デレる必要はないんです｡
なぜなら､ テキストを表示するだけなら､
テキストはアドレスとなるポインタの値を表示することになるからです｡
実際に表示したいのは､ textが指している値です｡
そして､ 終了です｡ いやいや､ 絶対に終わってませんよ｡ 私たちのフリーを呼びたい｡
ポインターを自由にしたい｡
終了時にはメモリが解放されるのに｡ そして､ 念のため､ textをnullと等しい値に設定しておくことも必要でしょう｡
では､ さっそくこれを組み立てて､ どうなるか見てみましょう｡
そして､ 正しい変数で読めていないから問題があるんです｡
ということで､ ここでは正しい変数を使用していません｡ サイズを使いたいのですが､
問題なさそうですね｡
ここで一つ違うのは､ テキストは文字ポインタなので､
参照を解除する必要がないことです｡
ポインタなどの場合は参照を解除するだけでよい｡ つまり､ パーセント s
を使用すると､ 自動的に文字ポインタの参照を解除することができます｡
これが､ 文字ポインタと他のポインタを使う場合の一つの違いです｡
他のポインターは､
実際には文字列を文字列配列にコピーしたりできないので､ 値を得るために参照を解除する必要があります｡
スターテキストイコールは絶対にできないので､ テキストをコピーしたい場合は常にstr
copyを使わなければならない｡
なぜなら､ 講義を思い出してください､ 実際には配列にデータを代入することはできず､
文字ポインタは配列なのです｡
だから､ ここではこれが正しいように見えるのです｡ 非参照にする理由はない｡
これを作って､ 走らせたいんです｡
そして､ テキストのリミットを入れていることにお気づきでしょう｡
例えば､ jasonに5,6と入力すると､ input is jasonとプリントアウトされるわけです｡
そして､ このプログラムを使って遊ぶことができます｡ しかし､ 繰り返しになりますが､ ここから得られる教訓は､
mallocを行う際の標準的なlibが含まれます｡
キャラクターポインターをNULLに初期化します｡ sizeはポインタではないので､
アンパサンドを使いながらscanfしてください｡
mallocするとき､ mallocはvoidポインタを返すので､ キャストする必要があります｡
常にmallocの中に入れておきたい｡ 割り当てたいものに対してsizeof演算子を実行します｡
回､
実際の文字数は何文字か､ 整数値｡ これは､ 整数やプリミティブなデータ型で､
技術的には文字に適用されます｡ サイズだけでいいんです｡
常にNULLかどうか､ 確認したいものです｡
文字列を使用しようとするとき｡
そして､ getに保存してあるテキストを入力してプリントアウトするだけです｡
そして最後に､ ポインタを解放して､ ヒープに返すことができるようにします｡
お役に立てれば幸いです｡ ありがとうございます｡