[Powered by Google Translate] 構造体について話してみましょう。 構造体は一緒に変数の束をグループ化する方法を提供してくれる 素敵なパッケージに。 それは、すぐに例を参照することが一番簡単です。 ので、我々は、構造体と言う その後、中括弧を開く そしてこの構造では、我々は、int型の年齢があるでしょう char *の名前、 それはそれだ。 それは、中括弧の後にセミコロンと奇妙に思えるかもしれません それは構造体と、実際に必要なのです。 任意の有効なタイプは、構造体の定義内に行くことができます。 ここでは、int型とchar *を使用してきました しかし、あなたはまた、言うと、100個の要素を配列を使用することができます あるいは別の構造体。 あなたはC言語で構造体を使用している場合、 あなたは、新しい型を作成している 他の種類のコレクションのうち。 ここでは、新しい型を作っている 整数とchar *のうち。 後で見るように、struct型 これまで使ってきた他のタイプに相当する多くの方法である。 通常、私はどのようにstruct型を比較す​​ることでしょう 整数型に似ています。 私たちが書いたコードは、有効なCですが、 それは、非常に有用なものではありません とガチャンという音は私たちに警告を与える。 構造体とそのが類似している方法を覚えていますか? さて、私たちは基本的には今言った int型、 これは非常に有用ラインではありません。 だから、実際にその型の変数を宣言してみましょう セミコロンの前に名称を与えることによって。 我々は変数学生を呼ぶことにします。 今、私たちは、学生と呼ばれる変数を宣言した 構造体で指定された型を持つ。 どのように我々は、構造体の内部変数に取得するのですか? これらの変数のための技術的には、名 メンバーです。 学生のstruct内の任意の特定のメンバーにアクセスするには、 あなたは、変数名にドットを追加 したいメンバーの名前が続きます。 そこでここでは、2つしか有効な可能性 student.ageアール とstudent.name。 そして、我々は何かのように行うことができます student.age = 12 とstudent.name =学生。 今、私たちは第二学生を作りたい場合はどうなりますか? あなたは、これらの行をコピーして貼り付けると思うかもしれない と、学生2か何かに学生を変更 それは動作しますが、 しかし技術的には、学生と学生2 同じ型を持っていない。 を参照してください、あなたはお互いにそれらを割り当てることはできません。 これは、これまでのところ、ためである あなたのstructは匿名となっています。 我々はそれに名前を付ける必要があります。 そのためには、構造体の名前を挿入します 単語のstructの後。 学生、 定義が続きます。 我々はまだ、すぐに型の変数を宣言することができます 我々は前にやったような構造体学生、。 我々は、それがS1と呼ぶことにします 構造体に名前を与えることによって、 我々は今、構造体の学生を使用することができます ほとんど同じ方法で、我々はintを使うだろう。 だから我々は、struct型の学生の変数を宣言することができます のような S2の構造学生。 配列のように、構造体は、ショートカットの初期化構文を提供します ので、我々は学生がS2構造体、と言うことができます 等しい 左中括弧3、S2。 ここでは、S2.ageは、3になります とS2.nameはS2を指すようになります。 int型であなたがすることができるすべてのものについて考える それらのほとんどはあなたは、struct学生型で行うことができます。 我々は関数パラメータの型として構造体の学生を使用することができます。 私たちは、新しい構造体の内部構造体の学生を使用することができます。 我々は、struct学生へのポインタを持つことができます。 我々は、構造体の学生のサイズを行うことができます。 構造体学生がタイプです ちょうどint型のようなタイプです。 我々はまた、S1とS2を割り当てることができます。 両方が同じタイプであるので、我々は行うことができますので、 S1 = S2。 我々が行う場合はどうなりますか S1.age = 10? すべてでS2変わりますか? 繰り返しになりますが、ごく普通の整数のように、構造体だと思います。 我々はいくつかのint型Yにいくつかのint型のXを割り当てた場合、 X = Yのような その後、Xを変更する 同様にX + + Yは全く変わるのでしょうか? Yは、ここで変更なども上記のS2は行いません。 S2.ageはまだ3です。 しかし、別の構造体を割り当てるときにあることに注意 ポインタのすべてはまだ、同じことを指している 以来、彼らは単にコピーされました。 あなたは、ポインタを共有したくない場合は、 あなたは、手動でそれを処理する必要があります 多分指すようにポインタのいずれかのメモリの1つのブロックをmalickingによって とデータを上書きコピー。 それはどこのstruct学生を書かなければならないのが面倒な場合があります。 タイプのデフを使用して、我々が行うことができます 型デフ 構造体 そして我々はそれ学生と呼ぶことにします。 今、我々はどこにでも生徒を使用することができます 我々は、struct生徒を使用するために使用すること。 このタイプのデフは、匿名構造体の そして、それは生徒を呼び出します。 しかし、我々はまた、学生の識別子を保持する場合 単語の構造体の隣には、typedef structの学生のように、 私たちは、同じ意味で今のstruct学生と学生の両方を使用することができます。 彼らも、同じ名前を持っている必要はありません。 我々はボブにdef構造体の学生を入力することができます その後、学生とボブを構造体 交換タイプであろう。 タイプに関係なくDEFの、 我々は、構造体への次の識別子が必要 もし構造体の定義 再帰的です。 たとえば、 DEF型のstructノード そしてそれは、int valのように定義されます そして、それは、別の構造体のノードを指すポインタを持つことになります。、 *次の構造体のノードのように。 そして、我々はそれをノードと呼ぶことにします。 この構造体は、再帰的である 構造ノードの定義は、その中に含まれているため、 構造ノードへのポインタ。 我々にはstructノード*次言わなければならないことに注意してください 構造ノードの定義の内側に、 タイプのデフは、私たちは、これを簡略化できるようにするために、まだ完成していないので、 単にノード*の隣にあります。 これに類似した構造体についての詳細を学びます ときに、リンクリストや木を扱う。 関数内の構造体についてはどうですか? また、これは完全に有効です。 我々は持っている可能性が funcを無効 これは、引数として取り 学生の その生徒で何かを行います。 そして、我々のように、学生の構造体として渡すことができます。 前からS1のFUNC。 structは振る舞う 整数は、関数に渡されただろうというときとまったく同じ。 機能は、S1のコピーを受信 ので、S1変更することはできません。 Sに保存されているそれのではなく、唯一のコピー あなたは、関数がS1を変更できるようにする場合、 機能は、学生* Sを取る必要があります そしてあなたは、次のように、アドレスによってS1を通過しなければならないでしょう。 学生* Sは、func&S1。 ここにアドレス渡しする別の理由があります。 私たちのstructは100フィールドが含まれていた場合はどうなりますか? 我々はfuncに生徒を渡す毎回、 私たちのプログラムは、関数の引数Sに100人のすべてのフィールドをコピーする必要があります それは、それらの大部分を使用しない場合でも。 機能は、学生を変更することを計画していないので、たとえ まだアドレス渡しは貴重であることができれば。 さて、我々は構造体へのポインタを作成したい場合はどうなるでしょうか? 我々のような何かができる 学生* S malloc関数に等しい 学生のサイズ。 静止画のサイズはここで働いていることに注意してください。 それでは、どのように我々は今、時代のメンバーにアクセスするにはどう ブロックのSが指している? あなたは最初に何を思うかもしれない * S.age = 4、 しかし、これは非常に動作しません。 これは実際にあると解釈されますので、 *カッコ内S.age = 4、 これは、コンパイル時にエラーとなります、 Sはstructまたはむしろ構造体へのポインタではないので、 などの点がここでは使用できません。 我々は何ができる (* S)である。年齢= 4 括弧は迷惑と混乱するかもしれない。 ありがたいことに、我々は特別な矢印演算子を持っている それは何かのように見える S - >年齢= 4。 年齢を参照して、これらの2つの方法 同等である と私たちは本当に今までに、矢印演算子を必要としない それは物事が立派に見えるのです。 Sは、構造体が含まれているメモリーの一部のブロックへのポインタであるため、 ポインタの矢印に従っているあなたは、S>年齢を考えることができます と年齢のメンバーをつかむ。 では、なぜ我々はこれまでに構造体を使うべきでしょうか? それは、単にプリミティブ整数で逃げることは間違いなく可能だ 文字、ポインタなど 我々は次の目的で使用していること; 代わりにS1とS2の前に、 我々はAGE1、AGE2、NAME1、およびname2あったかもしれない 別々の変数で、すべて。 これは、たった2学生と罰金です しかし、私たちがそれらの10を持っていた場合はどうなりますか? そして、どのような場合だけではなく、2つのフィールド、 学生のstructは、100フィールドを持っていた? GPA、コース、髪の色、性別、などなど。 代わりにわずか10構造体の、我々は千別々の変数を必要としています。 また、関数を考えてみましょう その唯一の引数との100フィールドで、その構造をとり、その し、すべてのフィールドを出力します。 我々は、構造体を使用しなかった場合、 我々は、その関数を呼び出す毎回 我々は、すべての100個の変数で渡す必要があります そして我々は、学生1の100個の変数を持っている場合、 学生のための2および100個の変数、 我々は誤って学生1からいくつかの変数を渡さないことを確認する必要があります 学生2から、いくつかの変数。 それは、構造体でそのミスを犯すことは不可能だ 全100個の変数は、単一のパッケージに含まれているからである。 最後の音符だけのカップル: あなたは素晴らしい、この点にすべてを理解していれば。 ビデオの残りの部分は、単に完全を期するためのものです。 構造体はポインタの任意の型を保持できるため、 彼らはまた、関数ポインタを保持することができます。 あなたは、オブジェクト指向プログラミングに精通している場合は、 これはオブジェクト指向のスタイルでプログラムを構造体を使用する方法を提供します。 別の時に関数ポインタの詳細。 また、時にはあなたは2点の構造体があるかもしれません その定義がお互いに依存しています。 たとえば、 我々は、構造体Aを及ぼす可能性があります として定義されている 構造体Bへのポインタ、 構造体B * X そして今我々は、struct Bを持つことができます ポインタとして定義されている 構造体Aに、 構造体A * Y しかし、これは、コンパイルされません 構造Bは構造体がコンパイルされた時点で存在しないので。 そして我々にはstruct Aと構造Bを交換する場合、 それから私達はちょうど同じ問題が残っているはずだ。 この時間は、使用して既存の構造体ではない。 これを解決するために、我々は書くことができます 構造体B; 構造体Aの定義の前に これは、前方宣言と呼ばれています。 これは単にコンパイラがそれを知ることができます 構造体Bは完全に以降または他の場所で定義される有効なタイプである。 私の名前はロブ·ボーデンであり、これはCS50です。 [CS50.TV]