こんにちは､ そしてお帰りなさい｡ 最後に､ 構造体について､
関数との関係､ パラメータや関数の引数として構造体を渡すことができること､
その方が効率的であることについてお話しします｡
だから､ 関数の引数としての構造体｡
Familyという構造体を宣言した後｡
この例では､
名前付きファミリーを作成します｡ この構造を関数の引数として渡すにはどうしたらよいでしょうか｡
だから､ ファミリーという構造があるんです｡
ここには､ 名前､ 父親､ 母親､ そして年齢を表すint型の文字配列がたくさんあります｡
それが､ 私たちの構造定義です｡
構造体であることは､ 構造体キーワードの後にタグ名があり､ 中括弧があることなどからわかります｡
では､ 実際にその構造体をsiblingsという関数に渡すにはどうしたらいいのでしょうか？
まあ､ 構造体を宣言するのと同じように､ パラメータ名として型を言うのでしょう｡
本当にわかりやすいですね｡ この場合､ ブール語の兄弟がいるわけです｡
SiblingsはBooleanを返しています｡
そして､ 2つのパラメータ､ 2つの構造体パラメータを受け取っています｡
構造体ファミリーの型である構造体タイプを特定する必要があります｡
さらに高度なC言語では､ この構造体をtypedfして別の名前にしたり､
ここで名前を短くしたりすることができますが､ typedについてはまだ説明していません｡
そのほうがいいかもしれませんね｡
しかし､ これは本当に必要な方法でしょう｡ 他のパラメータと同様に､ 構造体ファミリである型全体を定義し､
次に変数名を定義する必要があります｡
ここでは､ メンバー1とメンバー2という2つのパラメータを渡しているわけです｡
2人ともタイプは構造家です｡
そして､ 関数の内部でメンバーにアクセスしたい場合は､ 通常と同じようにメンバーにアクセスします｡
メンバー1とメンバー2はポインターではないので､ ダッシュや大文字は使いません｡ ポインターの場合､
何を指しているかを確認するために参照を解除する必要があるからです｡
ポインタじゃないから､ dotでいいんだよ｡ つまり､ メンバー1ドットマザー､ メンバー2ドットマザーです｡
メンバー1ドットマザーとメンバー2ドットマザーは文字配列で､
文字配列は基本的にポインタです｡
そこで､ strの比較に渡すことができる｡ つまり､ メンバー1の母親とメンバー2の母親が同じかどうかを調べているのです｡
そして､ もしそうであれば､ trueを返すことにしています｡
だって､ 二人の名前が同じで､ それが本当に名字になるなら兄弟なんだから｡
かなりわかりやすい｡
関数の宣言にその型の構造体があれば､
関数に引数を渡すのは簡単です｡
この関数も､ 2つのパラメータを持ち､ それぞれがfamily型の構造体である｡
構造体へのポインタを関数の引数として持ちたい場合はどうでしょう｡
そして､ 先ほども言いましたが､ 値で渡す､ cで渡すということをやっているので､
この方が良いのです｡
値で渡す場合は､ コピーする｡
多くのデータを含む構造体､ 大きな構造体を引数として持っている場合､
その構造体のすべてを実際の関数にコピーする必要があるのです｡
そのため､ これらの大きな構造をコピーするのに時間がかかる可能性があります｡
ポインタがあれば､ そのアドレスをコピーすればよいのですから､
ずっと速いですよね｡ そこで､ 構造体へのポインタをパラメータや関数として使用することで､
メモリの消費と､ すべての構造体のコピーにかかる時間を回避しています｡
さて､ 小さな構造体なら大したことはありませんが､
ポインタや構造体は絶対に大きなものを使いたいものです｡
この場合､ どうするかというと､ 構造体の種類を指定するのはそのままで､ あらかじめアスタリスクをつけておくだけです､
とても簡単ですね｡ また､ 構造体内のどのデータも変化させたくない場合は､
構造体型の前に定数を使用することができます｡
アドレスを変更させたくない場合は､ 構造体ファミリポインタの後に定数を置くことになります｡
しかし､ ここでは､ 同じことをやっているのです｡ なぜなら､ ポインタになったことで､
ドットの代わりにダッシュのgreater thanという新しいシンボルを使ってアクセスできるようになったからです｡
ここではドットを使わなくてもいいんです｡ なぜなら､ ポインターは最初に参照解除しなければならないので､
括弧でくくる必要があります｡ ポインターを参照解除してから括弧の外にドットを置く方が優先順位が高いので､ 大なり小なりダッシュを使う方がずっと簡単です｡
ダッシュと母より大きい､ ダッシュと母より大きい......どちらもポインタだから､
strの比較で渡すことができるんだ｡
同じであれば､ trueを返す｡ そうでなければ､ falseを返す｡ 非常にわかりやすい｡
また､ 構造体のメンバを一切変更できないようにしたい場合は､
先ほど述べたようにconst修飾子を使用することができます｡
構造体が指し示すものは､ ポインタの前に const を置きます｡
familyの前にもconst actuallyを入れるとか｡
この場合､ 家族にはタイプフがある｡
つまり､ ここではコンストラクタ・ファミリかコンストラクタ・ファミリ・ポインタということになる｡
そして､ また同じようにアクセスすると､ 何も修正されません｡ それでいいんですね｡
コンパイラは文句を言わない｡
また､ アドレス自体の改変を許さない場合は､ constant modifierを使用することができます｡
これらの構造体を変更しようとすると､ コンパイル時にエラーメッセージが表示されます｡
つまり､ ここでは家族の星と言い､
星の後に定数を置くのです｡
そして､ これが言っているのは､ p-memberの値､
つまりアドレスであるポインタの値は変えられないということです｡
しかし､ これもあまり意味がありません｡ 値で渡すということは､
実際にはアドレスのコピーを渡していることになるからです｡
だからこれは余計に､ やらなくていいんだけど､ やってもいいんだよ｡
そして､ ここでもまた､ pメンバーが何であるかのアドレスを変更できるようにしたいのです｡
この場合､ とにかくデータにアクセスして､ 等しいかどうかを確認するわけです｡
各パラメータ定義のインダイレクト演算子は､ 定数キーワードの前に置かれるようになりました｡
このアスタリスク､ パラメータ名の前に付いていないんです｡
ポインタに格納されているアドレスは､ アスタリスクの後なので変更できません｡
もし､ パラメータ名型の前にあったなら､ それが指している実際のものを変更できるようにしたいものです｡
もし､ パラメータ名の前に間接演算子があれば､ その前の定数は何を指しているのか､
変更できるようにしたいことを意味します｡
これは住所を言っているだけです｡
そのため､ ポインタに格納されているアドレスを変更することはできません｡
ここで保護されるのはポインタであって､ それが指す構造体ではありません｡
定数や他のポインタパラメータと同じで､ 構造体との違いはありません｡
ポインタである関数から構造体を返す場合､ 関数プロトタイプはこの戻り値を通常の方法で宣言に示さなければならない｡
だからここでは､ 私の楽しいポインターとデートするためにストラックと言わなければならないでしょう､
またはポインターではない､ それは問題ではありません｡
これは,
date型の構造体を返す引数のない関数のプロトタイプで, 関数から構造体を返すことは非常に簡単です． そして､ その価値は何なのか｡
さて､ これで1つの関数から複数の要素や1つのデータを返すことができるようになりました｡
構造体を返す場合､ 10個の値､ 10種類のデータ項目を返すことができます｡
なんてかっこいいんでしょう｡ 構造体を使用すると､ 関数から複数のものを返すことができます｡
とてもとても貴重なものです｡
そのため､ 構造体だけでなく､ 構造体へのポインタを返した方が便利な場合が多いのです｡
構造体へのポインタを返す場合､ ポインタはすべてヒープ上に作成されるため､
ヒープ上に作成されます｡
つまり､ もう少し長く使えるということです｡
そしてこれは､ 任意のタイミングで削除して管理できることを意味します｡
そこで､ この例では､ fundsという名前の構造体を作成しています｡
これは､ 銀行という名前の文字配列が含まれており､
ダブル､ 特定の長さのsavedという名前の別の文字が含まれています｡
ただ､ ファンレングスが50に等しいと仮定した場合｡
そして､ 二重に保存したものを搭載しています｡
その構造体をパラメータとするsumという関数があります｡
そして､ その中でやっていることは､ 最初の構造から得た銀行資金と貯蓄資金を加えて､
彼らが銀行に預けている金額を返すということなのです｡
この例では､ sumは単なるdoubleである｡
ポインターを返すわけではありません｡ ポインタをパラメータとして受け取っているだけです｡
そして､ メイン関数では､ stanという構造体変数（struct
funds型）を作成しています｡
いくつかの値で初期化し､ sumの呼び出しの合計を出力しているのです｡
そして､ この構造体を他の変数と同じように渡すだけです｡
ポインターではないので､ 参照を解除する必要はありません｡ 特別なことをする必要はないんです｡
関数宣言で構造体型があることを確認するだけで､ 他はすべて正常に見えます｡
いくつか注意点があります｡
先ほど､ 構造体を関数に渡すときは常にポインタを使うべきであると述べました｡
なぜ？ なぜなら､ 古いバージョンのcは構造体を渡すことはできないが､
ポインタを渡すことはできることを思い出してほしい｡
だから､ 後方互換性のようなものを回避することができる｡
古いバージョンのcを使用している場合､ あなたのプログラムは動作します｡
だから､ その1つのアドレスを渡すだけでも､
タイムコピーのため効率的なのです｡
しかし､ この場合､ 関数内で構造体へのポインターをパラメーターとして渡すと､
データの保護が弱くなります｡
そのため､ 呼び出された関数の操作によっては､ 元の構造体のデータに不用意に影響を与える可能性があります｡
そして､ ここで使いたいのがconst修飾子です｡
そして､ アスタリスクの後でもなく､ パラメータ名の前でもなく､
実際の型の前にconstを使用することになるのです｡
構造体を渡す利点は引数であり､ 関数は元のデータのコピーで動作する｡
元のデータで作業するよりも安全です｡
つまり､ ポインタではない構造体を引数として渡したいのは､ このときだけなのです｡
そして､ プログラミングのスタイルが少し明確になる傾向があります｡
構造体ポインタを引数として渡すのとは対照的に､ 構造体を引数として渡すことの主な欠点は､
古い実装ではコードが処理できないかもしれないこと､
時間と空間の浪費､ 特に大きな構造体を持つ場合は各メンバーに対して多くのコピーを行わなければならないことです｡
だから､ このことを肝に銘じておいてください｡
ほとんどの場合､ 構造体へのポインタを渡す方が効率的で､
時間の節約になります｡
プログラマは効率化のために構造体ポインタを関数の引数として使用し､ 必要に応じて定数を使用します｡
そして､ この組み合わせがやりたいことなのです｡
もし､ プロテクトが心配なら､ 関数ポインタを使うことで効率を上げ､
さらに const const を使うことで､ 関数内部で何も起こらないようにすればいいのです｡
構造体を値で渡すのは､ 小さい構造体に対して行われることがほとんどで､ そういうルールについて考えたいものです｡
ポインタでない構造体でも小さければOK｡
ここでも､ 構造体に関するいくつかの重要な概念と､ パラメータ､
引数としてポインタを渡すこと､ 同様にポインタを返すことがあります｡
これで､
実際にいくつかの実装を開始することができます｡ 多くの事例をご紹介しています｡ 私たちはコンセプトを理解しています｡ 構文を理解する｡
さて､ ここで皆さんに2つの課題を提示したいと思います｡ 実際にやっていただき､ 構文を覚えていただき､
もしプログラムの中で構造を作りたくなったら､ 手のひらを返したようにその方法を知っていただきたいと思います｡
そこで､ これから数回の講義で､ 構造に関するこのような話に親しんでもらうための課題を出します｡
ありがとうございます｡