人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

入れ子になった構造体について質問です。
下記プログラムを組みました。
コンパイルは通りますが、実行できません。
ポインタでつまずいていると思うのですが、ダメな理由が分かりません。
恐れ入りますが、宜しくお願いします。

#include <stdio.h>

void main(void)
{
struct name{
char *sei;
char *mei;
};

struct table {
struct name *n;
int age;
char *hobby;
};

struct table x,y;

x.n->sei = "Turing";
printf("sei = %s\n",x.n->sei);
}

●質問者: mizore_chan
●カテゴリ:コンピュータ
○ 状態 :終了
└ 回答数 : 3/3件

▽最新の回答へ

1 ● 勇者よっしー
●34ポイント ベストアンサー

y使ってないのはどうでもいいです
nの実体が無いです
まず
struct name n;
x->n = &n;
こんな感じでnの実体を作らないと。
試しに、今x->nには何が入ってますか?


mizore_chanさんのコメント
有難う御座います。 nはポインタで、charのポインタをメンバーに持つ構造体を指している という理解では間違いですか? 実体は"Turing"で、それを指したと考えたのですが。 宜しくお願いします。

TransFreeBSDさんのコメント
>> 実体は"Turing"で、それを指したと考えたのですが。 << +nは構造体のポインタ変数で、"Turing"は構造体ではありませんよね? --nは構造体のポインタ変数ですので構造体のポインタを代入します +nに代入していませんよね? --構造体のポインタは構造体を指し示すものですから構造体が必要です +nの指し示す先のメンバ変数に代入しようとしましたが…… --では何も代入されていないnは何を指しているのでしょうか?

mizore_chanさんのコメント
有難う御座います。 (1)nは構造体のポインタ変数 (2)"Turing"も構造体でない ポインタで型が異なるものを指しても エラーとか警告はでないのですね。 納得致しました。

TransFreeBSDさんのコメント
いや、質問のコードは +メンバ変数seiに代入していてcharのポインタなのでOK +メンバ変数nには代入してない +メンバ変数nを使ってるけど、コンパイル時には中身が確定しない --コンパイル時にエラーにはならない --ただ、コンパイラや設定によっては警告出たりするのかもしれない --実行時は別 C言語は実行時のエラー処理がプログラマ任せなので、変なポインタ使うと変な動作するか、OSに強制終了させられるか。なのでバグの温床になるというのは有名なお話。

mizore_chanさんのコメント
メンバ変数nの実体がなかったのが誤りですね。 構造体のメンバーに構造体へのポインタを使う場合、 (1)その構造体の実体があり、(2)それを指していることが必要という理解で宜しいでしょうか。 (私は、(1)(2)をやっていなかった)

勇者よっしーさんのコメント
そのとおりです! 今は「構造体内に構造体のポインタある理由が判らねぇえええ」と思ってるかも知れませんが、例えばこんな事も出来ます。 struct name n[100]; x.n = n; x.n->sei = "Turing"; x.n+1->sei = "Turing1"; x.n+2->sei = "Turing2"; x.n+3->sei = "Turing3"; あくまで例ですが

mizore_chanさんのコメント
有難う御座います。 やってみましたが、 x.n+1->sei = "Turing1"; x.n+2->sei = "Turing2"; x.n+3->sei = "Turing3"; の部分で、コンパイルエラーがでます。 >>>> -> か ->* の左には構造体のポインタが必要(関数 main ) n+1 という表現は正しいでしょうか? 宜しくお願いします。

勇者よっしーさんのコメント
今更ですが(一度回答したんですが消えてた?) x.n[1]->sei="Turing1" とか出来ます

2 ● a-kuma3
●33ポイント

table に、必ず name がついてまわるなら、こうした方が良いと思うな。

struct name{
 char *sei;
 char *mei;
};

struct table {
 struct name n; /* ポインタじゃなくする */
 int age;
 char *hobby;
};

struct table x;

x.n.sei = "Turing"; /* n はポインタじゃないので、-> じゃなくて、ピリオド */
printf("sei = %s\n",x.n.sei); /* こっちも */


【追記】

構造体での入れ子とポインタの使い方を理解したいので、
ポインタで無くするというのはナシでお願いします。

ラジャー。

二つの構造体が、正しく組み合わさって動くためには、以下のような関係になっている必要があります。
f:id:a-kuma3:20120610175049j:image

質問にあるソースだと、name 構造体の実体が作られていないこと、table 構造体の n メンバーが name の実体に相当する領域を指していないこと、が、正しく動かない理由です。

例えば、こんな感じ。

struct name{
 char *sei;
 char *mei;
};

struct table {
 struct name *n;
 int age;
 char *hobby;
};

struct table x;
x.n = (struct name *)alloca(sizeof(struct name));/* ★ */
x.hobby = "My hobby !";

x.n->sei = "Turing";
x.n->mei = "...";
printf("sei = %s\n",x.n->sei);

mizore_chanさんのコメント
有難う御座います。 構造体での入れ子とポインタの使い方を理解したいので、 ポインタで無くするというのはナシでお願いします。

a-kuma3さんのコメント
回答に追記しました。

mizore_chanさんのコメント
有難う御座います。 構造体tableのメンバーに構造体nameのポインタを用いるのは 使い辛いことが分かりました。 有りがとう御座います。

3 ● oil999
●33ポイント

下のように、構造体ポインタの実体(実アドレス)を代入してやる必要があります。

#include <stdio.h>

void main(void)
{
 struct name {
 char *sei;
 char *mei;
} name_r;

struct table {
 struct name *n;
 int age;
 char *hobby;
};

struct table x,y;

x.n = &name_r; /* ポインタの実体を代入 */
x.n->sei = "Turing";
printf("sei = %s\n",x.n->sei);
}

mizore_chanさんのコメント
有難う御座います。 実体が必要なんですね。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ