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

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
jay
記事: 314
登録日時: 14年前
住所: 大阪市
連絡を取る:

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

#1

投稿記事 by jay » 14年前

構造体の中で宣言した構造体型配列のポインタを引数として関数に渡し、そこからデータを参照して各処理を行う、という仕様を作ろうとしていますが上手くいきません。

具体的には

コード:

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

となっています。
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ

box
記事: 2002
登録日時: 14年前

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

#2

投稿記事 by box » 14年前

> enter_data(Data.Cmd);

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

>void enter_data(Cmd_t *p[30])

引数が、「Cmd_t型のポインターの配列」となっているのを修正して、
「Cmd_t型の配列へのポインター」としなければならないと思います。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
a5ua
記事: 199
登録日時: 14年前

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

#3

投稿記事 by a5ua » 14年前

修正の一例としては、以下のようになるでしょう。

コード:

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;
}

たかぎ
記事: 328
登録日時: 14年前
住所: 大阪
連絡を取る:

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

#4

投稿記事 by たかぎ » 14年前

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++;
}

jay
記事: 314
登録日時: 14年前
住所: 大阪市
連絡を取る:

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

#5

投稿記事 by jay » 14年前

上手くいったのはいいですが、返信が遅れてしまい申し訳ないです。

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

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

なんだか、以前先生に「ポインタは普段から意識して使わへんと、いざという時全っ然わからへんからな」と言われたのを痛感しました(苦笑)
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ

閉鎖

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