ページ 11

構造体型配列について質問です

Posted: 2011年5月03日(火) 22:33
by jay
構造体の中で宣言した構造体型配列のポインタを引数として関数に渡し、そこからデータを参照して各処理を行う、という仕様を作ろうとしていますが上手くいきません。

具体的には

コード:

typdef struct
{
 char name[64];

 int kind;
 int state1,stae2;
}Cmd_t;

typdef struct
{
  int img_num;

 Cmd_t Cmd[30];
}Data_t;

extern Data_t Data;
このように構造体の定義・宣言を行い

コード:

extern void enter_data(Cmd_t *p[30]);

void play_data()
{
 //
 //ここで構造体のデータを外部から読み込んでCmdsの各構造体に格納しています

 enter_data(Data.Cmd);
}

//別のcppファイルにて
Cmd_t  play_cmd;

void enter_data(Cmd_t *p[30])
{
 static int num=0;

 play_cmd.kind = *p[num]->kind;
 play_cmd.state1 = *p[num]->state1;
//他のデータも同様にplay_cmdに格納します

//play_cmdに格納したデータを元に必要な処理を行います

 num++;
}

こうしてpを配列のポインタとして宣言し
p[num]->
のような形でnumの値をひとつずつ増やしていくことでCmd[30]の中のデータを順番に参照できるかと思いました。

配列のポインタを引数として渡す時は[]を付けずに、配列の名前をそのまま渡せばいい(ハズ)ですのでData.Cmdを引数として渡せばData.Cmd[30]の構造体に中にあるデータを参照できるかと思ったのですが
error C2664: 'enter_data' : 1 番目の引数を 'Cmd_t [30]' から 'Cmd_t *[]' に変換できません。
というエラーが出ました、もう半日以上悩んだり調べたり色々試したりしているのですが上手くいきません。

構造体の中で宣言した構造体型配列のポインタを引数として関数に渡し、p[num]->のような形で操作するにはどうすればいいのでしょうか?
または、どこを修正すればいいでしょうか?


開発環境は
OS:Windows7
エディター:Visual C++ 2008 Express Edition

となっています。

Re: 構造体型配列について質問です

Posted: 2011年5月03日(火) 23:13
by box
> enter_data(Data.Cmd);

こういう風に呼び出したいのであれば、

>void enter_data(Cmd_t *p[30])

引数が、「Cmd_t型のポインターの配列」となっているのを修正して、
「Cmd_t型の配列へのポインター」としなければならないと思います。

Re: 構造体型配列について質問です

Posted: 2011年5月03日(火) 23:52
by a5ua
修正の一例としては、以下のようになるでしょう。

コード:

extern void enter_data(Cmd_t *p);

void play_data()
{
	enter_data(Data.Cmd);
}

Cmd_t  play_cmd;

void enter_data(Cmd_t *p)
{
	static int num=0;
	
	play_cmd.kind = p[num].kind;
	play_cmd.state1 = p[num].state1;
	
	num++;
}
【解説】

配列の名前だけ書いた場合は、その配列の先頭要素のアドレスとなります。
つまり、
&Data.Cmd[0];
とみなされます。
Data.Cmd[0]の型は、"Cmd_t"であり、そのアドレスなので、
&Data.Cmd[0]の型は、"Cmd_t *"となります。

そして、Cmd_t *pとして、配列の先頭要素アドレスが渡ってきたとき、
配列のi番目にアクセスするには、pまたは、*(p + i)と書きます。(これらは等価な表現です。)
pはの型は、"Cmd_t"となるので、後は、p.kindのように、ドット演算子でメンバーにアクセスできます。
また、(p + i)->kindのように、アロー演算子を使う表現も出来ます。


【以下おまけ】

ただし、上記の場合、配列の要素数の情報は関数には渡りません。
もし、30という配列の要素数の情報を残したい場合は、

以下のように、引数として要素数を渡すか、

コード:

void enter_data(Cmd_t *p, int n);

void play_data()
{
	enter_data(Data.Cmd, 30);
}
配列へのポインタを渡すことになるでしょう。(こちらは理解しにくい)

コード:

void enter_data(Cmd_t (*p)[30]);

void play_data()
{
	enter_data(&Data.Cmd);
}

void enter_data(Cmd_t *p)
{
	play_cmd.kind = (*p)[num].kind;
}

Re: 構造体型配列について質問です

Posted: 2011年5月04日(水) 11:09
by たかぎ
C++のようなので...

おそらく最も期待したものに近くなるのは次の書き方だと思います。

コード:

void enter_data(Cmd_t (&p)[30])
{
    static int num=0;
    
    play_cmd.kind = p[num].kind;
    play_cmd.state1 = p[num].state1;
    
    num++;
}

Re: 構造体型配列について質問です

Posted: 2011年5月04日(水) 22:17
by jay
上手くいったのはいいですが、返信が遅れてしまい申し訳ないです。

そんな訳で上手く仕様を作ることができました
boxさん、a5uaさん、たかぎさん、どうもありがとうございました。

特に懇切丁寧に解説して下さったa5uaさん、本当にありがとうございます。
バッチリ理解できました!

なんだか、以前先生に「ポインタは普段から意識して使わへんと、いざという時全っ然わからへんからな」と言われたのを痛感しました(苦笑)