こんにちは､ そしてお帰りなさい｡ この講義では､ 前回の課題であった参照渡しを理解するためのデモを行いたいと思います｡
参照渡しとは､ 関数内のパラメータがポインタを取ることです｡
では､ 新しいプロジェクトを作りましょう｡ 基本的なことですが､
新しいプロジェクト､ コンソール・アプリケーションc.
ここはかなりわかりやすい｡
このポインターをアンダースコアの参照渡しということにしておこう｡
ここでも､ 関数内部でパラメータを使ってデータを渡し､ そのデータが関数外部でどのように変更されるかを示しています｡
そこで､ まず最初に関数宣言と関数プロトタイプを作成します｡
これは､
プログラムのどこでも呼び出せるようにするために､ いつもやっておくといいことです｡ 正方形ということにしておきます｡
この関数宣言の主なものは､ ポインタを取るということです｡
つまり､ 終端ポインタを取るだけなので､ ここではint starとし､
あとは好きな名前をつけて､ セミコロンで終了させます｡
メイン関数では､ まず通常の整数変数を作成してint
numとし､ それをハードコードして9にします｡
そして､ これから行うのは､ square関数を呼び出すことです｡
square関数はデータを返さないので､ voidになります｡
4行目のsquare関数がポインタを取っているので､ 今度はアドレスを渡す必要があります｡
だから､ numを渡すことはできない｡ 実際にnumのアドレスを渡して､
セミコロンで終わらせる必要がある｡ そこで､ 関数名を使って関数を呼び出し､
変数のアドレスを渡しています｡
8行目のここの変数はポインタではないので｡
あとは基本的にnumの値をプリントアウトすればよい｡
また､ ここで気づくのは､ アドレスを渡しているので､ その変数のデータを関数自体の中で変更すると､
関数の外でも変更されることです｡
ここでは与えられた数値の2乗をパーセントdと言い､
改行を加えてnumを出力するだけですが､ numは9にはなりません｡
それだけは確かです｡
そして､ 通常の関数では0を返すだけです｡
そこで､ 実際に関数を実装し､ 定義する必要があります｡
定義としては､ ボイドスクエアということになりますね｡
整数ポインタを取ることが分かっているので､ int star xとします｡
そして今度は､ それをそのまま掛け算したいのです｡
しかし､ アドレスは変更しないようにしたい｡
しかし､ データ型の後に定数を付ける必要があります｡
なぜなら､ xの値やxが指しているアドレスを変更したくないからです｡
xの値を変えたくなければ､ constantと言うだろう｡
しかし､ xの値を変えたいのですから､ それだけで二乗することになります｡
そこで､ 単体で二乗するために､ まず､ 変えたいのはxの究極の値である｡
そこで､
インダイレクト演算子を使うことになる｡ アスタリスクで非参照にしなければならない｡
そして､ イコールと言うだけで､
x×xはしたくありません｡ Xはポインターなので､ 単にxの値を取得したいのではなく､
xが指し示すものの値を取得したいのです｡
だから､ もう一度､ 参照を解除して､
それを掛け合わせるのです｡ それを2回ほどデリケートにしています｡
ここで何が起こっているのかを簡単に理解するために､
これを括弧でくくるのは良いアイデアかもしれません｡
ポインタの参照を解除し､ その値を取得し､ その値で乗算して､
セミコロンを追加するだけです｡
つまり､
このプログラムを実行すると､ 81がプリントアウトされるわけです｡
numの値が出力されるんです｡ Numは､ そこにアドレスを渡しているので､ squareの内側が変化することになります｡
ポインタの値を実際に変更することはできないので､
型の後に定数を付けています｡
そこで､ ここではビルドと言い､ 宣言を変更していないように見えます｡
あとは､ すべてが正しいかどうかを確認するだけです｡
ポインタを一定にしたい場合は､ アスタリスクの後に置く必要があります｡
つまりint start定数とは､
numのアドレスであるxの値を変えられないということです｡
intの前やアスタリスクの前のinputの後にconstをつけると､
ポインタが指しているものの値を変更できないことを意味します｡
これで実行すると､ 出力が81になるはずです｡
繰り返しになりますが､ これが物語るのは､
データを修正したことです｡
この変数､
このローカル変数numは､ 関数内部で修正され､ その値が変更されました｡
それは普通じゃない｡ その概念を今まで学んでこなかったのです｡ それは参照渡しです｡
しかし､ 実際には､ アドレスのコピーを渡しているのです｡
だから本当に冗長なんです｡ 仮にポインタの値を変更したとしても､
ポインタの値のコピーですから､ 定数は必要ないんです｡
もし､ 既存の数値を使いたくなければ､ ポインターを作成し､
その分のメモリーを確保すればよい｡
そこで､ ここでやらなければならないのは､ int star numを作ることです｡
しかし､ まず最初にmallocをキャストする必要があります｡ mallocはvoidポインタを返しますが､
メモリを動的に割り当てることができるからです｡
そして､ ここでは､ 本当に1つの整数を作成しているので､
intのサイズを言うだけで､ メモリを確保してくれるのです｡
そして､ スクエア・ナンバーに合格すればいいのです｡
そして､ これを構築すると､
同じことをしますが､ 今度はnumの値もないので､
実際に何を計算すればいいのかわかりません｡ そこで､ 実際にnumの値（ここでは4とします）に代入して､ 参照を解除しなければなりません｡
そして今､
ビルドして実行すると､ 16個になるはずです｡
さて､ ここで唯一のことは､ 値をプリントアウトしたいので､ numと言いたいのです｡
そして､ 実行すると､ 16が表示されるはずです｡
そして､ それは本当に同じような行動で､ 私たちは16を見ることができます｡
ただ一つ違うのは､ アンパサンドで既存のメモリロケーションを指定するのとは対照的に､
ポイントが指し示すものに対してメモリを確保することです｡
ここでも重要なことは､ この数値は関数の外側で変化していることです｡
これは参照理解で渡される｡
ここで､ 非参照演算子､ 間接演算子を使って､
ポイントが指しているものの値を取得しているのです｡
関数がポインタを取り､ 私たちがポインタを持っていれば､ 名前を送るだけでよいことを理解してください｡
もし､ ポインターを取っていなくて､
実際には値であれば､ 参照を解除しなければならない｡
そして､ これはscanfと同じです｡
だからここでは､ アンパサンドと言うことになる｡
また､ プリントアウトする際にも､
ポインタではないので参照を解除する必要はなく､
ここでも同じことが言えます｡
そして､ コンスト2を理解する｡ intの星の前のconstは､ その点が指す値が変化しないことを意味しています｡
int startの後のconstは､ ポインタのアドレスが､ ポインタの値を変更することはできないと言っているのです｡
参考になったでしょうか｡
繰り返しになりますが､ 私のように構文を変えたり､ いろいろと弄ってみてください｡
多くのことを学ぶことができます｡ ありがとうございます｡