• ベストアンサー

構造体の中の構造体

typedef struct number{ int x; struct number *next; }Num; 初心者な質問で申し訳ないんですが、構造体の中に構造体があるのはどう解釈していいんでしょうか? typedef struct number{ int x; int y; }Num; の場合はNum a,b;がint a.x,a.y,b.x,b.yとなるのは分かるんですが・・・

質問者が選んだベストアンサー

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★構造体の中の構造体とは。 ・構造体Aに構造体Bや構造体Cが入っていても普通の変数と同じに解釈すれば良いです。  例えば  // 構造体A  typedef struct tagA_t {   int a;  } tagA;  // 構造体B  typedef struct tagB_t {   int b;  } tagB;  // 構造体C(AとBを含む)  typedef struct tagC_t {   tagA A;   tagB B;   int c;  } tagC; ・この場合は構造体Cに構造体Aと構造体Bが入れ子として入っています。  『tagC CC;』と宣言すると  『int CC.A.a』とか  『int CC.B.b』というアクセスが出来ます。 本題: ・今回は構造体の中に自分自身の『構造体ポインタ』が入っています。  これは『自己参照構造体』と呼ばれ『単方向リスト』、『双方向リスト』、『二文木』とかで  データを管理できる構造を持っています。 ・質問では『next』ポインタが1つですので『単方向リスト』を構成する構造体でしょう。  他の回答者さんと同じですが『鎖』のように次々に『next』ポインタで繋げるのです。  アクセス方法は  Num a; // Num 構造体の実体  Num *pa; // Num 構造体のポインタ    pa = &a; // pa に a ポインタをセット  pa->x = 123;  pa->next;  ↑  ここまでは分かりますよね。 ・もし next に2つ3つの構造体 Num がポインタで繋がれている状態ならば  pa->next->x = 456;  とか  pa->next->next->x = 789;  としてもアクセス(代入,参照)できます。  ※詳しくは下の『参考URL』をどうぞ。 ・以上。

参考URL:
http://www9.plala.or.jp/sgwr-t/c/sec15-5.html,http://tdweb.cssa.chs.nihon-u.ac.jp/ds/ds02.html
blade3322
質問者

お礼

詳しい説明ありがとうございます。 おかげで構造体というものがわかってきました。

その他の回答 (3)

  • hidebun
  • ベストアンサー率50% (92/181)
回答No.3

人と人とが手をつなぐイメージかな。(人=構造体) ポインタは次の人(もしくは前の人)と手をつなぐための手(ハンドル)です。 nextは、次の人へ。 prevは、前の人へ。(質問者さんの例にはないですが。) データをくさり状につないでおくと、いろいろ処理がやりやすくなります。

blade3322
質問者

お礼

なるほど、それが双方向リストですね。

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

「自己参照構造体」あるいは「線形リスト」で調べてみてください。

blade3322
質問者

お礼

わかりました。調べてみます。

回答No.1

構造体の中にあるのは構造体ではなく「構造体へのポインタ」です。 構造体の中の「構造体へのポインタ」は別(次)の構造体を指すポインタで、構造体が鎖のようにつながったデータ構造を表現しています。 □→□→…→□ 鎖の最後にある構造体の中の「構造体へのポインタ」にNULLを設定することで、鎖の末尾を表現します。

blade3322
質問者

お礼

なるほど・・・分かりやすい解説どうもです。 大体の感じがつかめてきました。

関連するQ&A

  • C言語の構造体についてなんですが。

    struct LIST {     struct Num* number;     struct LIST* next;/* 次の要素へのポインタ */ }*root; struct Num{     int a;     struct Num* next; /* 次の要素へのポインタ */ }*numroot; と構造体を定義したときに、 main(){     struct LIST *p;     for(p = root; p != NULL; p = p->next) ; } とすれば、pの先頭からNULLまでを参照していくことは分かるんですが、pのnumberの先頭からNULLまでの参照方法(プログラムのfor文の記述方法)がイマイチわかりません。つまり、構造体の構造体をどのように参照するかということです。 これを実現したい理由は、構造体内での数の格納を配列(固定長)ではなく可変長で格納したいからです。 分かる方は解答をお願いします。

  • 入れ子の構造体について

    例えば、入れ子の構造体を1つ使いたい場合、 struct bbb{ int b; }; typedef struct aaa{ struct bbb a; }AAA; AAA dt; と書くと、「dt.a.b = 10」とやれば、値等を設定できると思いますが、 入れ子の構造体を2つ使いたい場合も、同じように書けるのでしょうか? struct ccc{ int c; }; struct bbb{ struct ccc b; }; typedef struct aaa{ struct bbb a; }AAA; AAA dt; dt.a.b.c = 10; と書けるのでしょうか?こんがらがってしまって、どう書いていいのか・・。 2つでも出来るのであれば、コードの書き方を教えて頂けませんか?

  • 構造体のポインタにNULLが入らない

    typedef struct tag{ int number; char name[10]; struct tag *next; }DATA; という構造体があって、 DATA *p; と宣言し、 p->next == NULL; とすることはできないんですか? セグメンテーション違反になってしまうのですが。 pが指すnextにNULLを入れるにはどうしたらいいのでしょうか?

  • 構造体について

    typedef struct num{ char rv[1000]; struct number *next; struct number *prev; }Num; このような双方向のリスト構造に void aplist(Num **s,char ns[]){ Num *old, *new; if(*s==NULL){ *s = (Num *)malloc(sizeof(Num)*1); strcpy((*s)->rv,ns); (*s)->next = NULL; (*s)->ago = NULL; return;} old= (*s); while(old->next != NULL){ old = old->next;} new = (Num *)malloc(sizeof(Num)*1); strcpy(new->rv,ns); new->next = NULL; old->next = new; new->prev = old; 関数の中でこのようにnext,oldを指定していったのですが、これでよいでしょうか?また、このリストを逆方向(prevの方向)に表示していきたいのですがどのように書けばよいでしょうか?nsは1行の文字列で、各構造体に1行ずつ入れていっています。

  • 構造体の代入と比較

    構造体のコピーは以下のようで正しいと思いますが、 struct A { int a; }; struct x, y; x.a=1; y = x; 構造体の比較は if (x != y)ではいけないのでしょうか? 構造体に限らずクラスも同じ考えでしょうか?

  • 構造体型のポインタ変数を含む構造体

    struct seiseki_tag { Int32 math ; Int32 english ; Int32 science; } ; typedef struct seiseki_tag SEISEKI ; struct personal_tag { Char name ; Int32 num ; SEISEKI *sptr } : typedef struct personal_tag PERSONAL ; struct info_tag { PERSONAL person_info ; } ; typedef struct info_tag INFO ; たとえば、上記のように3つの構造体があり、PERSONAL構造体のメンバーに SEISEKI構造体の型を持つポインタ変数が含まれているような場合で、下記のように INFO型のポインタ変数からSEISEKI構造体のメンバーを参照する方法を教えてください。 PERSONAL構造体メンバーのnameやnumは INFO *info ; info->person_info.name ; info->person_info.num ; のように参照すると思いますが、sptrが示すSEISEKI構造体のメンバーへの アクセスができません。下記のように参照を試みたのですがコンパイルは 通るのですが、実際に参照できていませんでした。 INFO *info ; SEISEKI *seiseki ; seiseki = info->person_info.sptr ; seiseki->math ; 判りにくい説明で申し訳ありませんが、どなたか教えていただければと思います。 よろしくお願いいたします。

  • 構造体について

    以下のような構造体の宣言が合ったとき struct list { int a; char b[20]; struct list *next; }; struct list *add_list( int a, char *str, struct list *head );・・・1 struct list *del_list( int a, struct list *head );・・・2 1は引数の数が同じため問題ないのですが、2はどういう意味になるのでしょう?

  • 構造体の配列とメンバの配列

    typedef struct _ex_table1 {   int  x[10];   int  y[10]; }ETable1; ETable1 et1; int ans1; for( int a = 0; a < 10; a++ ){   et1.x[a] = a+10;   et1.y[a] = a*2; } for( int b = 0; b < 10; b++ ){   if( et1.x[b] == 15 ){     ans1 = et1.y[b];     break;   }   else{     ans1 = 0;   } } printf( "%d", ans1 ); ///////////////////////////////// typedef struct _ex_table2 {   int xx;   int yy; }ETable2; ETable2 et2[10]; int ans2; for( int aa = 0; aa < 10; aa++ ){   et2[aa].xx = aa+10;   et2[aa].yy = aa*2; } for( int bb = 0; bb < 10; bb++){   if( et2[bb].xx == 15 ){     ans2 = et2[bb].yy;     break;   }   else   {     ans2 = 0;   } } printf("%d", ans2 ); と言う感じに、微妙にソースを書いてみたのですが、 上のメンバ(x,xx)の値が正しいものがあったら、 対応する下のメンバ(y,yy)を出力したいと思っていますが、 構造体を配列にした場合と、構造体メンバを配列にした場合は どのように違うのでしょうか? 私には、同じように思えてしまいます。 どなたか、利点・欠点など教えていただけませんか? よろしくお願い致します。

  • 配列を含んだ構造体への値設定について教えて下さい。

    配列を含んだ構造体への値設定について教えて下さい。 下記のような構造体の定義があります。 typedef struct A_T { UINT64 a1; UINT32 a2; } A_t; typedef struct B_T { UINT32 b1; A_t b[8]; } B_t; 構造体B_tを関数の引数で渡し、A_tのa1とa2に値を設定したいのですが、プログラミング初心者の為、どのように作ればよいのかわかりません。 どうぞ教えて下さい。

  • DLLからEXEに構造体を渡すとき

    すいませんが、DLLからEXEに構造体を渡すときに どのようにしたらいいのでしょうか? 調べてみても EXE→DLLには載っているのですが、 DLL→EXEには調べ方が悪いのかわかりませんでした。 よろしくお願いいたします。 typedef struct _KOUZOU { int a; int b; } KOUZOU; (ここをどのように?) CALLBACK test() { KOUZOU kouzou1; kouzou1.a=1; kouzou1.b=2; return (ここをどのように?); }

専門家に質問してみよう