ページ 11

構造体の配列について

Posted: 2011年11月11日(金) 00:16
by platyくん
構造体の中に配列を入れようとしているのですが、初期化でうまくいきません。

コード:

struct weapon_conf{
	float attack[32];
	int rensya[32];
	int speed[32];
	int shot_type[32];//0→不使用
	bool get[32];
};

extern weapon_conf *w;

コード:

#include "weapon_conf.h"
struct weapon_conf *w;
void weapon_config(){
	if(loop_time == 0){
		//初期武器データを構造体で代入
		w->shot_type[0] = 0;
		w->shot_type[1] = 0;
		w->shot_type[2] = 0;
		w->shot_type[3] = 0;
	}
}
GameProg.exe の 0x003cd6ce でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x00000180 に書き込み中にアクセス違反が発生しました。
とエラー表示されてしまいます。
おそらくポインタにint型の数を代入しているからだと思うのですが、解決策が浮かびません。
どう修正すればいいのですか?

Re: 構造体の配列について

Posted: 2011年11月11日(金) 01:10
by h2so5
platyくん さんが書きました: おそらくポインタにint型の数を代入しているからだと思うのですが、
それが分かっているなら、ポインタを使わずに
struct weapon_conf w;
とすればOKではないでしょうか?

Re: 構造体の配列について

Posted: 2011年11月11日(金) 07:01
by beatle
h2so5 さんが書きました: それが分かっているなら、ポインタを使わずに
struct weapon_conf w;
とすればOKではないでしょうか?
僕が想像するに、恐らくstruct wepon_conf* 型の変数wに何も設定しておらず、NULLポインタアクセスになっています。
(0x00000180 に書き込み中にエラーがでていることから推測しました。sizeof(float) == sizeof(int) == 4な環境では普通、shot_type[0]のオフセットは0x180になります。)
platyくん さんが書きました: おそらくポインタにint型の数を代入しているからだと思うのですが、
というのは、多分

コード:

w->shot_type[0] = 0;
w->shot_type[1] = 0;
w->shot_type[2] = 0;
w->shot_type[3] = 0;
のことを言っているのだと思います。
この4行自体にはなんら変なところはありません。

問題なのは、wに何も代入しない状態でwepon_config()関数を呼び出していることにあります。

Re: 構造体の配列について

Posted: 2011年11月11日(金) 08:45
by non
3行目と4行目目の間に次の行を入れる。
w = (struct weapon_conf *)malloc(sizeof(struct weapon_conf ));

Re: 構造体の配列について

Posted: 2011年11月11日(金) 10:34
by platyくん
non さんが書きました:3行目と4行目目の間に次の行を入れる。
w = (struct weapon_conf *)malloc(sizeof(struct weapon_conf ));
一応解決しました。ですが、これだと関数を呼び出すたびにメモリー確保するみたいになりませんか?

Re: 構造体の配列について

Posted: 2011年11月11日(金) 10:46
by non
platyくん さんが書きました:一応解決しました。ですが、これだと関数を呼び出すたびにメモリー確保するみたいになりませんか?
もちろんそうですよ。これは、初期化する関数じゃないのかな?
いらなくなったらfreeを忘れないように。

Re: 構造体の配列について

Posted: 2011年11月11日(金) 10:52
by beatle
platyくん さんが書きました:
non さんが書きました:3行目と4行目目の間に次の行を入れる。
w = (struct weapon_conf *)malloc(sizeof(struct weapon_conf ));
一応解決しました。ですが、これだと関数を呼び出すたびにメモリー確保するみたいになりませんか?
もちろんそうなります。

nonさんの方法を使わず、例えばこのようにしても解決できます。

コード:

int main()
{
    struct weapon_conf w0;
    w = &w0;
    weapon_config();
    ...
}
もしくは、weapon_config関数がstruct weapon_conf*を引数に取るようにして

コード:

void weapon_conf(struct weapon_conf* w)
{
    // 中身は前と同じ
}

int main()
{
    struct weapon_conf w0;
    weapon_config(&w0);
    w = &w0;
    ...
}
なーんて方法もあります。
こうすると、グローバル領域にwを作る必要はあまりなくなってきます。
グローバル変数を使わないことが、多くの場合に「良いコード」とされるので、参考にしてください。