こんにちは､ そしてようこそ｡ 新しいセクションに入りました｡
今回は､ 構造についてお話します｡
これは､ 項目をグループ化することができるcの新しい概念で､
配列に似ているが､ より強力である｡
構造体とは何か､ 構造体をどう作るか､ どう使うかについてお話したいと思います｡
つまり､ cの構造体は､ 要素をグループ化するためのもう一つのツールなのだ｡
アレイと似ていると言いましたが､ 実はもう少し強力です｡
オブジェクト指向プログラミングに詳しい方なら､
Javaやc-plus plusなどのオブジェクト指向言語でプログラミングをする場合､
オブジェクトはデータメンバーだけで､ 実際の動作やメソッドはないと考えるのが普通でしょう｡
これは､ 異なる項目を一つの名前にまとめて､
本質的にデータの属性を表すことができるため､
開発する多くのCプログラムで使用することができる強力な概念です｡
例えば､ プログラムの中に日付を保存したいとします｡
日付は通常､ 月､ 日､ 年の3つの変数で構成される｡
そのデータを保存するために､ この3つの変数を作るのです｡
例えば､ int month equals 9 day equals 25 year equals
2015 と言うことです｡
あなたのプログラムでは､ 特定の商品の購入日も保存する必要があるとします｡
まあ､ プログラムで使う日付ごとに､ さらに3つの変数を作らなければならないでしょうけど｡
このように､
非常に繰り返しの多い作業となり､ 多くの変数を作成することになるのはおわかりいただけると思います｡
しかし､ 気づいてほしいのは､ これらの変数が論理的に関連しているということです｡ すべて日付です｡
本当は一緒にした方がいいんですけどね｡
このようなデータ型は､ ほとんど独自のデータ型であるべきで､ それを作成し､ さまざまな要素にアクセスできるようにする必要があります｡
いちいち日付ごとに3つの変数を作成する必要はないはずです｡
ここでもまた､ オブジェクトと､ 3つのデータ属性を持つクラスとの関係が出てくるわけです｡
ですから､ この3つの変数のセットを何らかの方法でグループ化することができれば､ もっと良いですね｡
そして､ これこそが､ structure要素の役割であり､ cである｡
これらの異なる要素を特定の名前でグループ化することができるのです｡
そして､ その名前の異なる変数を作成し､ その名前の要素､
異なるデータ属性にアクセスすることができます､
それらは実際にはメンバーと呼ばれます｡
では､ cで構造体を作るにはどうしたらいいのでしょうか｡
それはとてもとてもシンプルなことです｡ 構造宣言は､ 構造がどのように組み合わされるかを記述する｡
構造体の中にどんな要素があるのか｡
そして､ これらの要素を通常､ メンバーと呼びます｡
なぜなら､ まず構造を定義するか､ 構造を宣言して､ 構造の中に何があるのかを記述しなければならないからです｡
そのため､ struct キーワードを使用すると､ そのようなことが可能になります｡
struct キーワードを使用すると､ 構造体と呼ばれるさまざまな型の変数の集まりを定義し､
1 つの単位として扱うことができます｡
とても､ パワフルです｡
そのため､ この構造体キーワードを使えば､ 名前を指定するだけでよく､
通常､ この名前をタグ名と呼びます｡ この例では､ dateというタグ名にしています｡
しかし､ 構造体というキーワードがありますね｡ これは､ Cコンパイラに「これは特定の関数になりますよ」と伝えるためのキーワードです｡
これは､ 要素をグループ化することができる特定の機能を持つことができます｡
つまり､ 構造体がキーワード､ タグ名､
そして左中括弧と右中括弧､ さらにセミコロンで終わります｡
そして､ その内部には好きなタイプの変数を定義することができ､ ポインターを置くことも可能です｡
そして､ それらを構造体のメンバーと呼びます｡
つまり､ この文は､ Cコンパイラが理解できる日付構造を定義しているのです｡
これは､ cコンパイラに状態構造体が何を含むかを伝えるもので､
月､ 日､ 年の3つの要素である｡
この宣言に対して､ メモリは割り当てられない｡
繰り返しになりますが､ あなたが言っているのは､ これは存在する構造だということです｡
まだ使い始めてはいない｡ ただ､ こういう風に定義されるんだと言っただけです｡
これが日付構成になり､ このような構成になります｡
日付構造内の変数名､ 月､ 日､ 年は､ メンバーまたはフィールドと呼ばれます｡
構造体のメンバーは､ 構造体のタグ名dateに続く中括弧の間に表示されるので､
タグ名date｡
非常にシンプルな構文で､ これらの要素をdateという一つの名前の中にまとめています｡
また､ 配列と違うのは､ インデックスがないこと､
サイズを指定していないことです｡
全く同じデータ型ではありません｡
異なるデータ型を持つことができ､ 多くの異なるものを持つことができます｡
では､ この仕組みをどう活用するのか｡
さて､ dateの定義は､ 言語に新しい型を定義しています｡
intやdouble､ floatと同じように､ 別の型と考えることができます｡
あなたが定義したこの型以外は､ ほとんど列挙型と考えることができます｡
ただし､ enumは1つの値しか持ちません｡
この日付構造体は3つの値を保持することができるが､ 別のデータ型である｡
変数に struct to date 型を宣言できるようになりました｡
まさにその通りなんですね｡
todayという新しい変数を作って､ type struct
dateの型にすることができます｡
そして､ 今日は基本的に3つの価値を持つことができそうです｡
そして､ さらに日付を宣言する必要があれば､
同じ型の変数をさらに作ればよい｡
そのため､ 購入日のために3つの別々の変数､ 現在の日付のために3つの別々の変数､
請求日のために3つの別々の変数を用意する必要がなくなりました｡
その実際の構造体の異なるインスタンスの1つの変数または2つの変数を持つことができます｡
繰り返しになりますが､ これがいかに強力なものであるかに気づいていただければ幸いです｡
つまり､ この文は､ 構造体の日付､ 購入日の型になります｡
変数を宣言したので､ メモリが確保されました｡ この構造体に対してメモリが確保されました｡
メモリは3つの整数値､ または各変数の3つのメンバーに対して割り当てられるので､
メモリが確保されることになります｡
また､ アロケートされるのは､ そこにポインタが存在しないからです｡
その構造体の中にポインタがあれば､ そのポインタのためにメモリを確保する必要があります｡
でも､ この今日の日付構造体はとてもシンプルな構造体なので､ 最初はゆっくり始めますが､
3つのintが入っていて､ これらのメンバーは自動的に割り当てられています｡
しかし､ この前のスライドと今回のスライドとの違いをしっかり理解してください｡
構造体を定義することと､ その特定の構造体型の変数を宣言することは別です｡
ファイナンス構造は､ Cコンパイラに「これは構造体で､ これはその中に入っているデータです」と伝えるだけです｡
しかし､ 実際にその特定の構造体型の変数を宣言することは､
その構造体を使い始めるということなのです｡
これで､ 例の3つの要素にメモリが割り当てられ､ それらの要素にアクセスして設定できるようになりました｡
では､ 構造体のメンバにはどのようにアクセスするのでしょうか｡
さて､ 構造体の定義方法と構造体変数の宣言方法がわかったところで､
今度は構造体のメンバの参照方法について理解する必要があります｡
アクセスする必要があります｡ もし､ アクセスして値を見たり､ 値を設定したりできなければ､ 意味がありません｡
つまり､ 構造体変数名はポインタではないのです｡
そのため､ メンバーにアクセスするためには特別な構文が必要です｡
ポインターは通常､ アドレスの値だけを含むからです｡
また､ ポインターでない場合は､ 特別な構文が必要になります｡
構造体のメンバを参照するには､ 変数名の後にピリオドを記述します｡
通常､ ドット演算子のように呼ばれます｡
そして､ そのドット演算子ピリオドの後に､
その構造体の中のメンバ変数名を続けます｡
構造体変数名とメンバ名の間のピリオドはメンバ選択演算子と呼ばれ､
ドット演算子とも呼ばれる｡
変数名､ ピリオド､ メンバー名の間にはスペースを入れてはいけません｡
変数todayの日の値を25にするためには､ 次のようにすればいいのです｡
今日という変数名､
そしてドット､ どちらかの間にスペースは入れないでくださいということです｡
そして､ 構造体定義の中の要素名を指定するのですが､ これがdayなんです｡
そして､ 他の整数を割り当てるのと同じように､ それを割り当てるのです｡
私なら､ イコール代入演算子､
ここのリテラル定数､ セミコロンを使う｡
とても､ シンプルです｡ 年号をつけるなら､
今日かな｡ 年と､ 例えばイコール2015年と言えるでしょう｡
そして､ メンバーの値にアクセスしたいとき｡
たとえば､ monthのメンバー値にアクセスして12に等しいかどうかを確認したい場合にも､
ドット構文とメンバー選択演算子を使用します｡
そこで､ メンバー選択演算子を使って､ メンバーの値にアクセスすることができます｡
そして､ そのメンバー変数にアクセスするときは､
他の変数と同じように使用することができます｡
intであれば算術演算で使える｡
そのデータ型のルールに従うことになる｡
そこで､ この場合､ if文の中で等号を使うだけで､
実際に12に比較することができます｡
そして､ 例えば12に等しいとしたら､ 来月は1に等しいと言うことができます｡
それは､ ローカル変数に割り当てることができるかもしれません｡
では､ 例を見てみましょう｡ ここでは､ dateという構造体を定義しています｡
月､ 日､ 年の3つの要素からなる整数を用意しました｡
struct キーワードと中括弧があるので､ 定義していることがわかります｡
さらに､ 右中括弧には定義を終了するためのセミコロンがあることにも注目してください｡
この時点では､ この構造体のためのメモリは割り当てられていません｡
次の行では､ 実際にその型の変数を宣言しています｡ つまり､
int型の月､ 日､ 年の3つの要素を本質的に含む変数名todayのためにメモリを確保しているのです｡
この構造体の中の3つの要素にデータを割り当てるには､ ドット・メンバー・アクセスを使用すればよいのです｡
そこで今日は 月9日､ 今日です｡ 日は25日と今日に等しい｡ 2015年の年号です｡
その後､ 印刷したり､ そのデータにアクセスする場合は､ 割り当てた後､ 同じようにアクセスすることになる｡
そのメンバー選択：今日を利用すればいいのです｡ 月､ 今日です｡ 日､
今日です｡ 年です｡ そしてまた､ intなので算術演算ができる｡
パーセントdを使うか､ あるいは2にフォーマットしたい場合は､
パーセント2Iやパーセント2Dと言うことができます｡
つまり､ これは非常にわかりやすい構文で､
構造体を作って定義し､ それを使って､ ドットメンバー選択演算子を使ってアクセスするのは非常に簡単です｡
構造や表現についてはいかがでしょうか｡
さて､ 先ほどデータへのアクセスや算術式を使うことができましたが､ それと何ら変わりはありません｡
式の評価に関しては､ 構造体メンバは通常の変数と同じルールに従います｡
その構造体の内部に整数のメンバがあれば､ 他の整数のルールと同じことができます｡
足し算､ 引き算などの応用が可能です｡ キャラクタバッファであれば､ キャラクタバッファのルールしかできない｡
文字バッファの追加やマイナスなど､
通常はできません｡
つまり､ フロート､ ダブル､ すべての異なるデータ型は､
式の中でそれらのメンバーを使用するときに同じルールに従えばよいのです｡
そこで､ 一例をご紹介します｡
今日も言う｡ 年÷100＋1
yearはint型なので完全に有効であり､
int型の通常の変数を使用するのと変わりません｡
そのメンバー選択演算子を使うことで､ 異なる方法でアクセスするだけです｡
今はバリエーションがあります｡ 構造を定義する方法はさまざまです｡
cの素晴らしいところはその柔軟性で､ cでは様々な方法で構造を定義することができます｡
そのため､
構造体を定義する際に異なる構文が表示されることがあります｡
最初にお見せした例は､ 本当にその通りにしてください｡ タグ名は必ずつけるべきで､ コードのある場所で構造を定義し､
別の場所でその変数を宣言する必要があります｡
でも､
cはそのままだと､ とてもフレキシブルなんです｡ 実は､ 構造体の定義と変数の宣言は同じ行で行うことができます｡
また､ 匿名構造体や無名構造体を定義することも可能です｡
だから､ 自由度が高いんです｡ 実際に構造体を定義するのと同時に､
ある構造体の一部となる変数を宣言することは有効である｡
一番下に変数名を入れることができます｡ その方法をお教えします｡
構造体定義の終端セミコロンの前に､ 変数名（複数可）を入れる｡
また､ これらの変数には､ 通常の変数と同じように値を代入して初期化することができます｡
では､ それを見てみましょう｡
構造体の定義と同時に変数を宣言する方法もあります｡
そこで､
今回は､ 構造体の日付を定義しましたが､ todayという変数も作成しました｡
なぜなら､ 右中括弧の最後､ セミコロンの前の名前は､ date構造体型の変数の作成とdate構造体の定義の両方を行なっているからです｡
つまり､ この上の例では､ 構造体の変数を作っているわけです｡
それもまた､ 構造のインスタンスと呼ぶ｡ 今日という日｡
構造体の定義と同時に宣言される｡
だから今日はdate型の変数で､ 全部一度にやったんです｡
そして､ 実際にtodayを実行した直後に､
括弧を使ってこれらの変数を初期化し､
月イコール5､ 日イコールなど､
他の整数を初期化するのと同じようにすることができます｡
さて､ もうひとつの方法として､ 無名の構造体を作ることもできます｡
これはあまりできないので､
ちょっと制限されますね｡
しかし､ 実際にタグ名を提供する必要はありません｡
タグ名は､ 構造体キーワードの直後で､ 一番上にあることを忘れないでください｡
これまでの例では､ タグ名はdateでした｡
しかし､ その日付を提供する必要はありません｡
構造体を定義する際に､ 特定の構造体型の変数がすべて定義されている場合は､
名前を省略することができる｡
そして､ これが本当に意味するのは､ その構造を一度だけ､ 一回だけしか使わないということです｡
だから､ struct int day,
int year, int month と言って､ 同じように変数を宣言すればいいんです｡
しかし､ structキーワードの後にタグ名がないことにお気づきでしょうか｡
これはあくまで一つの構造です｡ 使うのは1回だけだから､
今日変数を作って､ もう二度と使わないようにするんだ｡
そして､ それが本当にデメリットであり､ 限界でもあります｡
一度だけ使うようなローカル構造体でない限り､ このようなことは決してしたくないものです｡
しかし､ このように無記名構造体､ 無名構造体として定義してしまうと､
これ以上のインスタンスを定義することができません｡
この構造体型の変数で､ プログラムに必要なものは､ すべて1つの文で定義する必要があります｡
複数の変数を作成することもできます｡ 今日のカンマと別の変数で､
複数の変数を作成することができます｡
複数の変数を初期化することができます｡
しかし､ この方法では､ 一番下にある変数宣言の後､ それ以上変数を作ることができないので､
少し制限があります｡
つまり､ 異なる構造を定義する方法は3つあるのです｡
一つの方法は､ タグ名で構造を定義し､ 変数を作らないことです｡
メモリが割り当てられるときに､ 別のインスタンスで変数を作成します｡
もう1つの方法は､ 変数と構造体を同時に作成してタグ名を付けておき､
プログラムの後でその構造体タイプの他のインスタンスや他の変数を作成できるようにする方法と､
3番目の方法として､ 名前を付けていない構造体を作成して､ 一番下に変数だけを作成する方法です｡
また､
これらの変数は､ 中括弧などを使って作成するたびに初期化することができます｡
そこで､ 今度は構造体を初期化します｡
構造体の初期化は､ 配列の初期化と非常によく似ています｡
各要素は中括弧で囲まれ､ カンマで区切られています｡
本当にここで学ぶべき新しいことはありません｡
中括弧の中の初期値は定数式でなければならない 変数は使えない､
配列と同じように見える
ここでは､ struct date
型の today 変数を作成し､ 最初のメンバが
7､ 2 番目が 2､ 3 番目が 2015 であり､ これは年の月日に対応する､
ということを述べています｡
そのため､ 配列の初期化と同様に､ 構造体に含まれる値よりも少ない値がリストアップされる可能性があります｡
3つすべてを指定する必要はなく､
2つだけ指定すれば､ 月と日が初期化され､ 年は初期化されません｡
これで日付が決まるわけですね｡ の1つです｡ 月～12月
date1. を10に変更したが､ 日付の初期値は与えなかった｡ 年です｡
また､ 初期化リストでメンバー名を指定することもできます｡ この方法では､
実際に順番を決めておく必要はありません｡
好きな順番に並べられるし､ それに左右されることもない｡
だから､ 次のようなことができるのです｡ member equals value
と struct date, date one. ドット月イコール12と言えるでしょう｡
つまり､ 最初の構文は､ 中括弧の中にドットでメンバーを設定し､
ドット月イコール12コンマ ドット日イコール10と値を代入するだけです｡
その点が必要です｡ その点が重要なので､ その点を忘れないでください｡
ドットの前のインスタンスは必要ありません｡
つまり､ この次の例では､ 日付構造変数todayの年メンバを2015に設定するだけです｡
ここでは､ 他のメンバー変数のいくつかを省略することができることを忘れないでくださいということです｡
そして今回は､
当日の月を認めているので､ 年号を2015年にするだけです｡
先ほどのケースでは､ 実際には年を省略し､
月と日付をそれぞれ12と10に設定しただけです｡
また､ 複合リテラルを使った代入も可能です｡
さて､ それは一体何なのかというと､ 複合文字です｡
複合リテラルと呼ばれるものを使用すると､ 1つのステートメントで1つ以上の値を構造体に割り当てることができます｡
これはC11だけかもしれないと思っています｡
しかし､ ここでは今日､ struct
date today変数を作成したと仮定して､ 実際に括弧の中にstruct
dateを入れています｡
そして中括弧の中は､ 9コンマ25コンマ2015と言っています｡
そして､ これは複合リテラルです｡
この文は､ プログラムのどこにでも表示することができます｡
つまり､ 実際にドット・メンバを使って初期化したり値を代入したりするのとは対照的に､ 今日の構造体を実際に初期化した後に､
プログラム中のどこにでもこれを置くことができるのです｡
宣言文ではありません｡
これは複合リテラル代入である｡
タイプキャスト演算子は､ コンパイラに式の型を伝えるために使われる｡
そのため､ キャストや構造体の日付など､ 括弧で囲ったものが必要です｡
値のリストはキャストの後に続き､ その順番で構造体のメンバに割り当てられますが､
これは順番に依存します｡
つまり､ 構造体変数を初期化するのと同じように記載されているわけです｡
この場合も､ 各メンバー変数を別々の行で個別に代入する必要がないのが利点です｡
一行ですべて行うことができ､ OKこれが今日のこの変数の新しい値です､
と言うことができます｡
また､ 先ほどのドットメンバー記法で値を指定することも可能です｡
このように一行でやるか､ 別々の行でやるかだけでしょう｡
この方法では､
初期化したように見えますが､ 複合リテラルを使っています｡
この方法の利点は､ 引数がどのような順番で現れてもよいということで､
前回と同じように
繰り返しますが､ これらの代入の鍵と違いは､ 初期化で行われるのではなく､
プログラムのどこか他の場所で､ その型に新しい値を代入していることです｡
この講演では､ たくさんの良い情報を得ることができました｡
構造体について､ その強力さと､ 異なる要素や異なる変数を1つの名前にグループ化する方法について説明しました｡
その構造を定義しています｡ 構造を定義する方法はさまざまです｡
そして､ 変数の宣言も必要です｡
この変数があれば､ ドットメンバー選択演算子を使って､
その構造体にアクセスし､ データを代入することができる｡
そして､ 初期化だけでなく､ さまざまな記法や方法についても説明します｡
構造体をかなり使うことになります｡
この構文に慣れるために､ いくつかの課題を用意します｡
しかし､ これはあくまで構造のスタート地点に過ぎません｡ また､ ネストした構造体について､
ポインタと構造体をどう使い分けるかとか､ そういう話もしなければなりません｡
このセクションは楽しくてエキサイティングなものになると思いますので､ 頑張ってください｡ ありがとうございます｡