構造体の中に構造体が入っているソースコードは、現場でもよく見かけます。
なので、構造体の構造体があるソースコードについて、今回は説明していきます!
構造体の中に構造体を入れるコード
とりあえずサンプルコードを見ていただきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
#include<stdio.h> /*--------- 構造体の宣言 ---------*/ /* 生徒情報の構造体 */ typedef struct { char *name ; //名前 int studentNum; //出席番号 char *address ; //住所 }st_StudentInfo; /* 教室情報の構造体 */ typedef struct { char *className ; //クラス名 st_StudentInfo studentList[30] ; //クラスの生徒情報 }st_ClassInfo; /*--------- 関数のプロトタイプ宣言 ---------*/ void func(st_ClassInfo *ptr_classInfo); /*------------------------------------------------*/ /* main関数 */ /*------------------------------------------------*/ int main() { st_ClassInfo OneOfThree; //構造体の定義 /* 構造体の初期化 */ OneOfThree.className = "3-1"; OneOfThree.studentList[0].name = "青木康介" ; OneOfThree.studentList[0].studentNum = 1 ; OneOfThree.studentList[0].address = "XXXXXX" ; /* 構造体の中身を出力 */ func(&OneOfThree); return 0; } /*------------------------------------------------*/ /* sub関数 */ /*------------------------------------------------*/ void func(st_ClassInfo *ptr_classInfo) { printf("クラス名...%s\n",ptr_classInfo->className); printf("名前...%s / 出席番号...%d / 住所...%s\n",ptr_classInfo->studentList[0].name,ptr_classInfo->studentList[0].studentNum,ptr_classInfo->studentList[0].address); } |
図を書くと、以下のような状態ですね。
それでは具体的に、構造体の構造体があるときの使い方を見ていきましょう!
構造体の構造体のメンバ変数の参照方法
構造体のメンバ変数を参照するには、構造体の定義名に”.”(ドット)を付けることで参照できました。
構造体の中の構造体になっても同様で、“.”(ドット)を付ければ参照することが出来ます。
構造体がポインタの場合のメンバ変数の参照方法
構造体がポインタの場合は、”->”(アロー演算子)でメンバ変数を参照することができましたね。
ただし、構造体の構造体はアドレス(ポインタ)でない場合は、”.”(ドット)を付けることでメンバ変数を参照することが出来ます。
ここが混同するのでややこしいかもしれません。
もう一度サンプルコードを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
#include<stdio.h> /*--------- 構造体の宣言 ---------*/ /* 生徒情報の構造体 */ typedef struct { char *name ; //名前 int studentNum; //出席番号 char *address ; //住所 }st_StudentInfo; /* 教室情報の構造体 */ typedef struct { char *className ; //クラス名 st_StudentInfo studentList[30] ; //クラスの生徒情報 }st_ClassInfo; /*--------- 関数のプロトタイプ宣言 ---------*/ void func(st_ClassInfo *ptr_classInfo); /*------------------------------------------------*/ /* main関数 */ /*------------------------------------------------*/ int main() { st_ClassInfo OneOfThree; //構造体の定義 /* 構造体の初期化 */ OneOfThree.className = "3-1"; OneOfThree.studentList[0].name = "青木康介" ; OneOfThree.studentList[0].studentNum = 1 ; OneOfThree.studentList[0].address = "XXXXXX" ; /* 構造体の中身を出力 */ func(&OneOfThree); return 0; } /*------------------------------------------------*/ /* sub関数 */ /*------------------------------------------------*/ void func(st_ClassInfo *ptr_classInfo) { printf("クラス名...%s\n",ptr_classInfo->className); printf("名前...%s / 出席番号...%d / 住所...%s\n",ptr_classInfo->studentList[0].name,ptr_classInfo->studentList[0].studentNum,ptr_classInfo->studentList[0].address); } |
サンプルコードの35行目で、OneOfThreeの構造体はポインタでfunc関数に渡しました。(関数先では、*ptr_classInfoというポインタの構造体名)
サンプルコード43行目のfunc関数の引数を見ての通り、構造体は*ptr_classInfoというポインタになっているため、構造体OneOfThreeのメンバ変数(classNameとstudentList[])は、”->”(アロー演算子)で参照します。
しかしstudentList[]はポインタではないため、構造体配列studentList[]のメンバ変数(name,studentNum,address)に関しては、”.”(ドット)で参照する必要があります。
構造体の構造体をポインタで渡す場合は?
あまりないと思いますが、構造体の構造体をポインタで関数に渡す場合は、どんな方法で渡すのでしょうか?
以下がサンプルコードになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
#include<stdio.h> /*--------- 構造体の宣言 ---------*/ /* 生徒情報の構造体 */ typedef struct { char *name ; //名前 int studentNum; //出席番号 char *address ; //住所 }st_StudentInfo; /* 教室情報の構造体 */ typedef struct { char *className ; //クラス名 st_StudentInfo studentList[30] ; //クラスの生徒情報 }st_ClassInfo; /*--------- 関数のプロトタイプ宣言 ---------*/ //void func(st_ClassInfo *ptr_classInfo); void func(st_StudentInfo *ptr_studentInfo); /*------------------------------------------------*/ /* main関数 */ /*------------------------------------------------*/ int main() { st_ClassInfo OneOfThree; //構造体の定義 /* 構造体の初期化 */ OneOfThree.className = "3-1"; OneOfThree.studentList[0].name = "青木康介" ; OneOfThree.studentList[0].studentNum = 1 ; OneOfThree.studentList[0].address = "XXXXXX" ; /* 構造体の中身を出力 */ func(&(OneOfThree.studentList[0])); return 0; } /*------------------------------------------------*/ /* sub関数 */ /*------------------------------------------------*/ void func(st_StudentInfo *ptr_studentInfo) { printf("名前...%s / 出席番号...%d / 住所...%s\n",ptr_studentInfo->name,ptr_studentInfo->studentNum,ptr_studentInfo->address); } |
サンプルコードの36行目で、構造体の構造体(studentList[])は、今回はポインタ(アドレス)でfunc関数に渡されています。
構造体の構造体は、*ptr_studentInfoというポインタになっているため、構造体studentList[]のメンバ変数(name,studentNum,address)は、”->”(アロー演算子)で参照します。
このように、「何がポインタになっているか?」が分かっていれば、”->”(アロー演算子)を使うのか”.”(ドット)を使うのかが判別できるようになります!
最後に
構造体の中に構造体があるパターンは、結構これからも見ると思いますので、理解を深めておいてください!