構造体の宣言法について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
kopi
記事: 19
登録日時: 6年前

構造体の宣言法について

#1

投稿記事 by kopi » 6年前

こんにちは。いつもお世話になっています。

下のようなコードにおいて、構造のイメージがつかめません。

コード:

typedef struct tree_node tree_node_t;
struct tree_node
{
    int value;
    tree_node_t *children[10];
};

typedef struct tree tree_t;
struct tree
{
    tree_node_t *root;
    int count;
};
とりあえず現段階での理解状況を述べます。

コード:

typedef struct tree_node tree_node_t;
ここで、tree_nodeという型 を tree_node_t型として宣言して、

コード:

struct tree_node
{
    int value;
    tree_node_t *children[10];
};
tree_node型の構造体の中で、int型のvalue と tree_node_t型の*children[10]を宣言。
もう一つの構造体の宣言部も同様に考えたのですが、どちらもどういう構造をしているのかイメージが掴めないのです。解説していただけると幸いです。

例えば、

コード:

struct seiseki {
	int no;		/* 学生番号 */
	char name[20];	/* 氏名 */
	double average;	/* 平均値 */
};
という宣言なら、「seiseki型のメンバはno, name, averageの3つから構成されてるのか―」とイメージできるのですが。

コード:

typedef struct tree_node tree_node_t;
また、この部分においては、
「 typedef 既にある型 新しい名前; 」
という認識なのですが、tree_nodeはまだこの時点では定義されていないからエラーは出ないのかなーと思ったり。

ご教授よろしくお願いいたします。
最後に編集したユーザー kopi on 2014年1月13日(月) 21:16 [ 編集 1 回目 ]

アバター
みけCAT
記事: 6296
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 構造体の宣言法について

#2

投稿記事 by みけCAT » 6年前

C++のポインタは、int型へのポインタでも、double型へのポインタでも、構造体へのポインタでも、
全て環境によって一定のサイズ(例えば4バイト)です。
そのため、差す先の構造体の具体的なサイズがわからなくても、とりあえず確保したいのがポインタだということがわかれば、
領域の確保はできます。

同様に、構造体のポインタを宣言するための「前方宣言」と呼ばれるテクニックもあります。

コード:

struct hoge;

void useHoge(hoge* h);

struct hoge {
	int foo,var;
}

void useHoge(hoge* h) {
	if(h)h->var=2*h->foo;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

kopi
記事: 19
登録日時: 6年前

Re: 構造体の宣言法について

#3

投稿記事 by kopi » 6年前

みけCAT さんが書きました: 同様に、構造体のポインタを宣言するための「前方宣言」と呼ばれるテクニックもあります。
教えていただきありがとうございます。
前方宣言について知らなかったため、調べてみたところ次のような文を見つけました。
*** http://p.booklog.jp/book/74354/page/1868230 から引用***
構造体型の中に、同じ構造体型のメンバを持たせたい時は 「不完全型の前方宣言」をしておきます。

コード:

struct ListItem; /* 構造体型 (不完全型) の前方宣言。*/

  struct ListItem /* 構造体型の定義。*/
  {
     int value;
     ListItem* p_prev;  /* メンバで、自身の型を使っているため、前方宣言が必要。*/
     ListItem* p_next;
  };
***引用終了***

ここで疑問なのですが、この場合は

コード:

  struct ListItem /* 構造体型の定義。*/
  {
     int value;
     struct ListItem* p_prev;
     struct ListItem* p_next;
  };
と書くことも可能ですよね?
最後に編集したユーザー kopi on 2014年1月13日(月) 21:39 [ 編集 1 回目 ]

アバター
みけCAT
記事: 6296
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 構造体の宣言法について

#4

投稿記事 by みけCAT » 6年前

kopi さんが書きました:***ネットから引用***
出典が示されていないので、これは引用ではなくて無断転載ですね。
kopi さんが書きました:ここで疑問なのですが、この場合は

コード:

  struct ListItem /* 構造体型の定義。*/
  {
     int value;
     struct ListItem* p_prev;
     struct ListItem* p_next;
  };
と書くことも可能ですよね?
gcc4.8.1では通りました。
http://ideone.com/unN9BU
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: 構造体の宣言法について

#5

投稿記事 by ISLe » 6年前

kopi さんが書きました:ここで疑問なのですが、この場合は

コード:

  struct ListItem /* 構造体型の定義。*/
  {
     int value;
     struct ListItem* p_prev;
     struct ListItem* p_next;
  };
と書くことも可能ですよね?
タグにC言語が指定されていますね。
C++ではstructもクラス定義のキーワードなので省略できますが、C言語では省略できません。
そのように「書かなければいけない」です。

どうしてC++の話になったのか分かりませんが。

アバター
みけCAT
記事: 6296
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 構造体の宣言法について

#6

投稿記事 by みけCAT » 6年前

ISLe さんが書きました:どうしてC++の話になったのか分かりませんが。
ごめんなさい、間違えました。

C言語で検証し直し→http://ideone.com/yf1CiK
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ISLe
記事: 2648
登録日時: 9年前
連絡を取る:

Re: 構造体の宣言法について

#7

投稿記事 by ISLe » 6年前

kopi さんが書きました:

コード:

typedef struct tree_node tree_node_t;
ここで、tree_nodeという型 を tree_node_t型として宣言して、
typedefで定義された型は、単に読み替えが行われるだけです。
新しい型が生成されるわけではありません。
例えばC++で、tree_node_tとstruct tree_nodeでオーバーライドできるのはどちらか一方だけです。
kopi さんが書きました:

コード:

struct tree_node
{
    int value;
    tree_node_t *children[10];
};
tree_node型の構造体の中で、int型のvalue と tree_node_t型の*children[10]を宣言。
ポインタの理解が不十分かと思います。
後者のchildrenは、tree_node_tへのポインタ(tree_node_t*)型の要素10個の配列です。

kopi
記事: 19
登録日時: 6年前

Re: 構造体の宣言法について

#8

投稿記事 by kopi » 6年前

みけCAT さんが書きました:出典が示されていないので、これは引用ではなくて無断転載ですね。
失礼しました。URLを記載した文に編集させていただきました。

またプログラムも示していただきありがとうございます。
ISLe さんが書きました: typedefで定義された型は、単に読み替えが行われるだけです。
新しい型が生成されるわけではありません。
なるほど。絡まっていた糸が解けた気がします。
つまり

コード:

typedef struct tree_node tree_node_t
と書いてあるなら、tree_node_t = struct tree_node と考えていいのですよね。
ISLe さんが書きました: ポインタの理解が不十分かと思います。
後者のchildrenは、tree_node_tへのポインタ(tree_node_t*)型の要素10個の配列です。
今まで勘違いしていました。tree_node_t型のchildrenを宣言するのではなく、childrenがtree_node_tを指すということですね。

考えてみた内容をコメントアウトして記載してみました。

コード:

typedef struct tree_node tree_node_t;   /* struct tree_node型 を tree_node_tとして読み替え */
struct tree_node   /* 前方宣言した構造体tree_nodeの中身は・・・ */
{
    int value;      /* これと */
    tree_node_t *children[10];   /* tree_node_t(= struct node)を指すポインタ */
};
間違っているところや理解しているのかどうか怪しい点があればご指摘いただけるとありがたいです。

アバター
へにっくす
記事: 630
登録日時: 8年前
住所: 東京都

Re: 構造体の宣言法について

#9

投稿記事 by へにっくす » 6年前

5行目の/* tree_node_t(= struct node)を指すポインタ */にツッコミ
・struct nodeでなくstruct tree_node。
・ポインタが10個、とまで書くべきですね。
written by へにっくす

kopi
記事: 19
登録日時: 6年前

Re: 構造体の宣言法について

#10

投稿記事 by kopi » 6年前

へにっくす さんが書きました:5行目の/* tree_node_t(= struct node)を指すポインタ */にツッコミ
・struct nodeでなくstruct tree_node。
・ポインタが10個、とまで書くべきですね。
struct node ではなく struct tree_node ですね。書き間違えてしまいました。
おっしゃる通り、ポインタが10個あるということもちゃんと書くべきでしたね。

かなり分かってきたので、ひとまずこれで解決とさせていただきます。
質問に答えていただいた、ISLeさん、みけCATさん、へにっくすさん、ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る