キャラの構造体管理

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
マント

キャラの構造体管理

#1

投稿記事 by マント » 14年前

前に館についての質問をさせてもらったのですが
申し訳ない、今回もすんごい初心者の質問です

構造体にキャラのx座標とy座標を覚えさせておきますよね
関数を抜けたら値を忘れてしまうのですが
構造体の値を忘れさせないようにするにはどうすればいいのでしょうか?
変数の場合はstaticを使えばいいですが構造体の場合は?

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

Re: キャラの構造体管理

#2

投稿記事 by box » 14年前

マント さんが書きました: 変数の場合はstaticを使えばいいですが構造体の場合は?
変数定義と構造体定義とをごちゃ混ぜにしているところに問題がありそうです。

構造体定義を使っていない変数の場合にstaticで解決することがわかっているならば、
当該の構造体定義を用いて定義した変数をstaticにすれば解決するのではないでしょうか。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

マント

Re: キャラの構造体管理

#3

投稿記事 by マント » 14年前

ここのりゅうじんろくの館を今、拝見さしてもらったのですが
staticって文字がないですよね?あれは一体、どうなっているのでしょう?

ちょっと質問がずれましたがお願いします

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

Re: キャラの構造体管理

#4

投稿記事 by box » 14年前

マント さんが書きました:ここのりゅうじんろくの館を今、拝見さしてもらったのですが
私はそこを見たことがないので、わかりません。

ところで、先ほどの回答に対する意見や感想は何かありますか?
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#5

投稿記事 by softya(ソフト屋) » 14年前

Dixqさんによると龍神録は初心者に分かりやすうようにグローバル変数を多用しているそうです。
これはプログラマーの間では、あまり良くないこととされていますので出来れば避けられることをお勧めします。

で、変数の値が保たない現象ですが、変数の寿命と変数のスコープを勉強されたほうが良いでしょう。

[変数の寿命]
変数は基本的に{}で示されるブロック内の寿命であるが、staticを付けた場合はプログラム起動から終了までの寿命となり初期化も起動時の一度しか行われない。逆にstaticがないと毎回初期化される。
それと関数外に宣言した場合は、これもプログラム起動から終了までの寿命となる。

[変数のスコープ]
ローカルスコープ:関数内や{ブロック}内のローカル変数として宣言した場合。そのブロック{}内でしか参照できない。
ファイルスコープ:関数外でかつstatic宣言した場合。そのコンパイル単位であるファイル内からしか参照できない。
グローバルスコープ:関数外でかつ、staticを付けなかった場合。extern宣言をすると別cppからでも参照可能になる。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マント

Re: キャラの構造体管理

#6

投稿記事 by マント » 14年前

〉〉ソフト屋さん
自分は分かっているつもりでいたのですがこれがわからないってことは
知識不足ってことですかね 
ヒープ領域ってのがありましたがそれがカギなのでしょうか

〉〉boxさん
boxさんがしてほしい意見ってこのことでしょうか?↓
「メンバにstaticをつけることができない」
このことが気になっていたのですが構造体をstaticにする場合、
構造体の先頭にstaticってつけないといけませんね
メンバにつけようとすると初期化子が多すぎると言われてしまいます
ではxとyだけ記憶させておいて同じ構造体に入っているその他の要素は
記憶しなくていい場合、どうすればいいのでしょう?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#7

投稿記事 by softya(ソフト屋) » 14年前

>ヒープ領域ってのがありましたがそれがカギなのでしょうか

それも違います。基本的にはmallocなどで使うのがヒープ領域です。
C言語規格(JISX3010)のレベルの話だとヒープ領域と言う言葉自体ありません。これはOSなどの環境依存の話だからです。
マント さんが書きました: このことが気になっていたのですが構造体をstaticにする場合、
構造体の先頭にstaticってつけないといけませんね
メンバにつけようとすると初期化子が多すぎると言われてしまいます
ではxとyだけ記憶させておいて同じ構造体に入っているその他の要素は
記憶しなくていい場合、どうすればいいのでしょう?
それと構造体の宣言と変数の実体宣言の話がごちゃ混ぜになっています。
記憶クラスのstaticは変数実体をどうメモリに割りつけるかの話ですので構造体の宣言に混ざってはいけません。
つまり、structのメンバにはstaticを付けれませんし、実体の伴わない構造体の宣言時にstaticを付けることは出来ません。

コード:

struct tag_st {
 static int a; ← メンバ毎に記憶クラスは変えれないのでエラーになります。
};
static struct tag_st {  ← 変数の実体を作っていないでエラーになります。
  int a;
};
static struct tag_st {  ← これは変数の実体があるのでOKです。
 int a;
} st;
それとメンバ毎に保存しなくて良いものと保存したいものあるとの事ですが、保存しなくて良いのなら構造体にそもそも入っている意味が無いのではないのでしょうか?
構造体からに抜いてローカル変数で良いのでは?検討してみてください。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マント

Re: キャラの構造体管理

#8

投稿記事 by マント » 14年前

今、思ったんですけど画像ファイルの名前って記憶しておく必要ってありますかね
今までは画像ハンドルと同じ構造体に入れていたのですが
ハンドルに代入した後、不必要になるなら
ファイル名は別の構造体に入れておくのが普通なのでしょうか?

それとソフト屋さんって確かRPG講座をやられていましたよね
あの講座ではグローバル変数は極力、使わないがコンセプト?だった気がするのですが
あの講座では主人公の座標はどうなっていたのでしょう

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#9

投稿記事 by softya(ソフト屋) » 14年前

マント さんが書きました:今、思ったんですけど画像ファイルの名前って記憶しておく必要ってありますかね
今までは画像ハンドルと同じ構造体に入れていたのですが
ハンドルに代入した後、不必要になるなら
ファイル名は別の構造体に入れておくのが普通なのでしょうか?
入れておくことは設計の自由ですが、入れていない場合も多いでしょうね。
入れても入れなくても大してプログラム的な無駄が出るわけではないので気にした事はないです。
マント さんが書きました: それとソフト屋さんって確かRPG講座をやられていましたよね
あの講座ではグローバル変数は極力、使わないがコンセプト?だった気がするのですが
あの講座では主人公の座標はどうなっていたのでしょう
構造体に定義されていて、関数間は構造体ポインタを渡しています。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

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

Re: キャラの構造体管理

#10

投稿記事 by box » 14年前

softya(ソフト屋) さんが書きました:

コード:

staic struct tag_st {  ← これは変数の実体があるのでOKです。
 staitc int a;
} st;
本当にOKなのでしょうか。

構造体のメンバーをstaticにできるのかできないのか、というのは、
構造体定義と同時にその構造体を使った変数を定義しているかしていないかによって
本当に結果が異なってくるのでしょうか。

私にはよくわからないので、教えてください。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

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

Re: キャラの構造体管理

#11

投稿記事 by box » 14年前

それとマントさん、
ご自身の質問に対して何か回答が付いた後、
何の前ぶれもなしにその回答とは無関係な別の話をする傾向があるようですね。
それでは、円滑なコミュニケーションができないのではないでしょうか。

>ところで、先ほどの回答に対する意見や感想は何かありますか?

と書いたのは、上記の傾向があることを踏まえてのものです。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#12

投稿記事 by softya(ソフト屋) » 14年前

box さんが書きました:
softya(ソフト屋) さんが書きました:

コード:

staic struct tag_st {  ← これは変数の実体があるのでOKです。
 staitc int a;
} st;
本当にOKなのでしょうか。

構造体のメンバーをstaticにできるのかできないのか、というのは、
構造体定義と同時にその構造体を使った変数を定義しているかしていないかによって
本当に結果が異なってくるのでしょうか。

私にはよくわからないので、教えてください。
申し訳ない。それは書き間違いですね。直しておきました。
コンパイル確認しておくべきでした。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マント

Re: キャラの構造体管理

#13

投稿記事 by マント » 14年前

>>ソフト屋さん
ポインタで受け渡しすると値を忘れずに済むのでしょうか?

〉〉boxさん
これは失敬しました 
度重なる無礼をどうかお許しください 

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#14

投稿記事 by softya(ソフト屋) » 14年前

マント さんが書きました:>>ソフト屋さん
ポインタで受け渡しすると値を忘れずに済むのでしょうか?
staticに関しては書き間違い修正しました。もう一度確認をお願いします。
ちなみにポインタで受け渡しすると値が消えないのではなくて、変数寿命を考慮して関数間で構造体ポインタを受け渡しています。
寿命が消えた構造体のポインタ値は絶対に使ってはいけない値です。実際に寿命が消えたポインタ値を受け渡すプログラは書けますが使ったら重症バグを産みます。

参考プログラム。このプログラムを実行してみてください。予想外の値が表示されると思います。
この場合は値が変になる程度かも知れませんが、場合によってはプログラムは異常終了します。

コード:

#include<stdio.h>

struct tag_st {
	int x;
	int y;
	int z;
};

struct tag_st *sub1()
{
	struct tag_st st;
	return &st;
}


void sub2(struct tag_st *pst)
{
	struct tag_st st;

	pst->x = 1;
	pst->y = 2;
	pst->z = 3;
	
	st.x = 5;
	st.y = 2;
	st.z = 7;

}

int main()
{
	struct tag_st *pst;
	
	pst = sub1();
	sub2(pst);
	
	printf( "pst->x=%d\n", pst->x );
	printf( "pst->y=%d\n", pst->y );
	printf( "pst->z=%d\n", pst->z );
	
    return 0;
}
ちなみにcygwinでgccの場合。
pst->x=5
pst->y=0
pst->z=9
コンパイラや実行環境で変わるはずです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マント

Re: キャラの構造体管理

#15

投稿記事 by マント » 14年前

ありがとうございます
サンプルプログラムのサブ2関数でstの値を埋めているのには
どういった意味があるのでしょうか?気になります

それとポインタで渡す意味の「寿命の考慮」というのが
イマイチ意味が分からないのですがどういうことか詳しく願います

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#16

投稿記事 by softya(ソフト屋) » 14年前

マント さんが書きました:サンプルプログラムのサブ2関数でstの値を埋めているのには
どういった意味があるのでしょうか?気になります
sub1とsub2のstruct tag_st st;は違う変数だよって意味とローカル変数なのでstruct tag_st st;が偶然同じアドレスを指している可能性があるってのを狙いました(処理系・コンパイルオプション依存なので良い子はやってはいけません)。まぁ、狙ったとおり同じアドレスを指していたようですが、yとzはその後のprintf処理系で破壊されたようです。
マント さんが書きました:それとポインタで渡す意味の「寿命の考慮」というのが
イマイチ意味が分からないのですがどういうことか詳しく願います
sub1のstruct tag_st st;はsub1を抜けたときに寿命は尽きていてstruct tag_st st;だったメモリ空間は他の変数などに割り当てらることが決まっています。
なので、寿命が尽きた構造体のポインタ値を使ってsub2やmainでsub1のstruct tag_st st;構造体変数の内容を参照・書き換えしていることは非常に危険なことだと認識して欲しいです。
今はワザと分りやすいのですが、みなさん結構平気でこれに近いことをやりますので「寿命の考慮」と言う言葉を使わせてもらいました。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マント

Re: キャラの構造体管理

#17

投稿記事 by マント » 14年前

なるほど、これは分かりづらい…
自分は正直、バグってどんなふうに生まれるんだと疑問に思っていましたが
こういう凡ミスから生まれることもあるんですね…恐ろしい

で、まだ疑問が解決していなかったことを思い出したので
再度、お聞きして申し訳ないですが
ソフト屋さんのRPG講座はローカル変数であるにかかわらず
staticしていなかった気がします なんで値が消えてないんですか?
ポインタってところが鍵なのですか?
mallocが鍵なんですか?

物わかりが悪くて申し訳ない
腹が立つかもしれんがお許しください

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#18

投稿記事 by softya(ソフト屋) » 14年前

ゲームのデータは、gameMain.cppのs_GameMainDataで管理してますのでファイルスコープで寿命は関数外なのでプログラム起動中ずっとです。つまりローカル変数ではありません。
あとmallocで管理しているものありますが、ポインタはs_GameMainDataに保存されていはずです。もしローカル変数だと思われるものがあったら具体名を上げていただけますか。そのほうが説明しやすいです。

ちなみにmallocされたメモリ領域はfreeするかプログラムが終わるまでが寿命です。つまり自分が決めるんですね。
プロでも一番多いミスはメモリをfreeしたにもかかわらず、そのメモリポインタを使うというミスです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マント

Re: キャラの構造体管理

#19

投稿記事 by マント » 14年前

mallocとstaticの違いがイマイチ分かりませんでしたが
そういやfreeにできるかできないかの違いがありましたね
またもや質問がずれるかもしれないのですが
率直に言うとmallocってなんの為にあるの?ってことです
メモリ領域を確保しないと構造体の実体?ができないのでしょうか?
うまく言葉にできませんがmallocがないとどうなるのでしょう

それとセーブするときに便利な構造体の入れ子なのですが
一々、長い名前を書くことが面倒なのです
セーブする直前に構造体にまとめるというやり方はできませんかね

今度こそ最後にしますのでどうかお願いします

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#20

投稿記事 by softya(ソフト屋) » 14年前

マント さんが書きました:mallocとstaticの違いがイマイチ分かりませんでしたが
そういやfreeにできるかできないかの違いがありましたね
またもや質問がずれるかもしれないのですが
率直に言うとmallocってなんの為にあるの?ってことです
メモリ領域を確保しないと構造体の実体?ができないのでしょうか?
うまく言葉にできませんがmallocがないとどうなるのでしょう
個数やサイズが不定な場合はmallocを使います。
個数がサイズ分かっているならstaticを使ってください。

【追記】
経験がないと分からないでしょうから、まずstaticだけで書くことを心がけてみてください。
もし、それで書いていて出来ないことや不便や無理を感じたりメモリが足らなくなったらmallocの出番かもしれません。

マント さんが書きました:それとセーブするときに便利な構造体の入れ子なのですが
一々、長い名前を書くことが面倒なのです
セーブする直前に構造体にまとめるというやり方はできませんかね
構造体のポインタ値(void*)とサイズを持ったポインタリストを作れば良いのでは?
そのポインタリストを使って読み込みと書き出しをします。

ただし、構造体の入れ子でも同様ですが構造体中にポインタがあるとロード時に破綻するので構造体中にポインタがあるのは禁止です。
これも初心者がよくやるミスですね。あとグラフィックハンドルもロード時に再現方法を考える必要があります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#21

投稿記事 by softya(ソフト屋) » 14年前

ちなみに変数の寿命を操る方法。その1。
sub1でstaticを使う。

コード:

#include<stdio.h>

struct tag_st {
	int x;
	int y;
	int z;
};

struct tag_st *sub1()
{
	static struct tag_st st;
	return &st;
}


void sub2(struct tag_st *pst)
{
	struct tag_st st;

	pst->x = 1;
	pst->y = 2;
	pst->z = 3;
	
	st.x = 7;
	st.y = 6;
	st.z = 5;
}

int main()
{
	struct tag_st *pst;
	
	pst = sub1();
	sub2(pst);
	
	printf( "pst->x=%d\n", pst->x );
	printf( "pst->y=%d\n", pst->y );
	printf( "pst->z=%d\n", pst->z );
	
    return 0;
}
実行結果
pst->x=1
pst->y=2
pst->z=3
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#22

投稿記事 by softya(ソフト屋) » 14年前

変数の寿命を操る方法。その2。
sub1でmallocを使う。

コード:

#include <stdio.h>
#include <stdlib.h>

struct tag_st {
	int x;
	int y;
	int z;
};

struct tag_st *sub1()
{
	struct tag_st *pst = malloc(sizeof(struct tag_st));
	return pst;
}


void sub2(struct tag_st *pst)
{
	struct tag_st st;

	pst->x = 1;
	pst->y = 2;
	pst->z = 3;
	
	st.x = 7;
	st.y = 6;
	st.z = 5;
}

int main()
{
	struct tag_st *pst;
	
	pst = sub1();
	sub2(pst);
	
	printf( "pst->x=%d\n", pst->x );
	printf( "pst->y=%d\n", pst->y );
	printf( "pst->z=%d\n", pst->z );
	
    return 0;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#23

投稿記事 by softya(ソフト屋) » 14年前

変数の寿命を操る方法。その3.
そもそもsub1で変数の実体を作らない。mainで実体を用意する方法です。
この場合、struct tag_st st;はローカル変数ですがmainが終了するまでの寿命なので実質プロがラムが終了するまでの寿命と同義です。

コード:

#include <stdio.h>

struct tag_st {
	int x;
	int y;
	int z;
};

void sub2(struct tag_st *pst)
{
	struct tag_st st;

	pst->x = 1;
	pst->y = 2;
	pst->z = 3;
	
	st.x = 7;
	st.y = 6;
	st.z = 5;
}

int main()
{
	struct tag_st st;
	struct tag_st *pst = &st;
	
	sub2(pst);
	
	printf( "pst->x=%d\n", pst->x );
	printf( "pst->y=%d\n", pst->y );
	printf( "pst->z=%d\n", pst->z );
	
    return 0;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マント

Re: キャラの構造体管理

#24

投稿記事 by マント » 14年前

これで最後とほざきましたが申し訳ない
今度こそ最後にしますので願います

mallocが分からないので調べてみたのですがどうしてもわからないことがありました
ソフト屋さんのコードではロード関数を呼び出して
そこでmallocをして値を返してゲームメイン関数で構造体に保存
ってなっていた気がするのですが 
ロード関数の構造体は忘れてしまってもいいので
ゲームメイン関数の方の構造体をmallocしないとおかしいんじゃないかと思いまして
勿論、間違っているのは知っていますがどうなのでしょう?


それと画像ハンドルの取得のためにchar.cppに構造体がありましたよね
構造体がcharのとgamemainので二つあるのでメモリを多く喰うと思い、
ポインタをgamemainから渡して直接、書き換えたほうが良いと思っているのですが
やっぱり速度の問題とかがあるんですかね


私自身、話が下手と痛感しているので言っている意味が分からなかったら言ってください

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#25

投稿記事 by softya(ソフト屋) » 14年前

これが最後と書くのは意味がないので止めましょう(前にも書いた気がしますが)
今までのやり取りから、色々と分かっていない部分があるのは想像できますので気が済むまでやった方が良いです。
前にも同じ様なやりとりしたと思いますが、同じところを形を変えて質問されているだけだと思います。
たしか前違う名前でしたよね?名前を統一してもらわないと過去のトピックの記述と一貫性が取れないので気をつけてくださいね。フォーラムルールにも違反します。

さて、本題ですが私の設計では、関数側でmallocしたものはポインタしか返さず呼び元で保存するときもポインタのまま保存しているはずです。
そもそも構造体定義を隠蔽しているので呼び元では構造体のサイズが分からずmallocできないはずです。
mallocしてる所が呼び出し元にあるますか?

前回書きましたがマントさんが気になる具体的なゲームメイン関数のその構造体の定義部分を取り出してみてここに書いてみてください。
マントさんが思っているものと私が思っているものが違っているかも知れません。
マント さんが書きました:それと画像ハンドルの取得のためにchar.cppに構造体がありましたよね
構造体がcharのとgamemainので二つあるのでメモリを多く喰うと思い、
ポインタをgamemainから渡して直接、書き換えたほうが良いと思っているのですが
やっぱり速度の問題とかがあるんですかね
ほとんど上で書いたことと同じですがchar.cppの構造体の構造はchar.cppからしか見えないのでgamemain.cppでは構造体の実体は宣言できません。
ぜひ、試して見ることをお勧めします。

[提案]
ずっと考えているだけでは真に理解出来ないはずですので、今までのやり取りの内容も自分なりに私が書いた様にサンプル化して書いてここに掲載してみてください。
マントさん自信が検証のために書いたコードを一度も見たことがないので、何処まで理解しているか私は疑問視しています。
書けないなら理由も教えて下さい。

言葉で語るより、より雄弁に理解度がソースコードに反映されます。言葉ベタならなおさらです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マント

Re: キャラの構造体管理

#26

投稿記事 by マント » 14年前

いろいろと…すいません

コード:

void load(chara *chara1){
    chara1->image=LoadGraph(aaa.png);
}

void gamemain(){
    load(&chara1);
    chara1=(chara)malloc(sizeof(chara));
}

さっき言っていたものを二つ合わせたものがこれです

1つめはロード関数から返ってきたキャラ管理オブジェクトを
違う構造体に代入するのではなくポインタを渡して直接、値を書き換えること

2つめはロード関数のキャラ管理オブジェクトにmallocを使うのではなくて
ロード関数を使った後のできあがった構造体にmallocを使うこと


このことが間違っていることは知っていますが素人頭だとこうなるんじゃないかと
考えてしまいます 
スコープの意味は知っていますができないyうnina

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#27

投稿記事 by softya(ソフト屋) » 14年前

名前を変えたことの返答をいただいていないのですが、前の名前と今度どの名前にするか明確にしてくださいね。それと提案の部分はどうされますか?

で本題のことですが
load(&chara1); これだと先にchara1と言う構造体の実体が必要ですね。でもgamemainでは構造体の構造はわかりませんので構造体の変数は宣言できません。chara chara1;と書くとエラーです。
chara1=(chara)malloc(sizeof(chara)); sizeof(chara)するためにはchara の構造体が宣言されいないダメですが、ここでは未定義です。sizeof(chara)はエラーになります。
この load(&chara1);で呼び出せるchara1変数はポインタではなく実体ですので、chara1=(chara)malloc(sizeof(chara)); と言うよなこと後ですることも出来ません。

私のやっていることをすごくシンプルにまとめたものです。コンパイルも通ります。リンクはWinMainがないのでエラーになりますけど。
無理やり1ファイルで書いたので変なことしてますが、struct tag_CharObject {を最後に書くことでvoid gamemain()から、struct tag_CharObjectの内容は参照できないようになっています。

コード:

#include "DxLib.h"

//	無理やり1ファイルで再現したもの

///////////////////////////////////////////////////////
//	charヘッダと仮定してください。

// 構造体のtypedef
typedef struct tag_CharObject *CharObject_t;

// 関数のプロトタイプ宣言
CharObject_t load();

///////////////////////////////////////////////////////
//	ここからはgamemain.cppです。

//#include "char.h"

void gamemain()
{
	CharObject_t charObj = load();
}

///////////////////////////////////////////////////////
//	ここからは、char.cpp

//#include "char.h"

struct tag_CharObject {
	int x;
	int y;
	int image;
};

//--------------------------------------
//	キャラ読み込み
//--------------------------------------
CharObject_t load()
{
	//	メモリ確保
	CharObject_t charObject = (CharObject_t)malloc(sizeof(struct tag_CharObject));
	//	初期化
	charObject->x = 0;
	charObject->y = 0;
	charObject->image = LoadGraph("aaa.png");
	//	ポインタを戻す。
	return charObject;
}

この私の書いたソースコードの並びのままで

コード:

void load(chara *chara1){
    chara1->image=LoadGraph(aaa.png);
}
 
void gamemain(){
    load(&chara1);
    chara1=(chara)malloc(sizeof(chara));
}
と同じ事をしてみてください。あるいは少々変えても構いません。決して関数や構造体の位置は変えてはいけません。
かならずコンパイルしてみると良いでしょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マント

Re: キャラの構造体管理

#28

投稿記事 by マント » 14年前

こちらの名前で統一させてください こっちが気に入りましたので すいません

コード:

 
typedef struct chara *Chara1;
 
chara1 load();
 
 
void gamemain()
{
      chara1 chara2 = load();
}
 
 
struct chara{
    int x;
    int y;
    int image;
};
 

chara1 load()
{
   
    chara1 chara2 = (chara1)malloc(sizeof(struct chara));

   chara2->x = 0;
     chara2->y = 0;
     chara2->image = LoadGraph("aaa.png");

    return chara2;
} 

ここで質問なのですがgamemainでまだ定義されていない構造体が宣言されていますよね
これっていいのでしょうか?それともポインタだと特別なのでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#29

投稿記事 by softya(ソフト屋) » 14年前

名前でchara1,chara2と付けるのは悪い癖だと思うのでやめたほうが良いと思います。どれがtypedefでどれが変数名なのか区別しづらいですよ。
私みたいな付け方もひとつの方法ですが、構造体名なのかtypedefなのか単なる変数名なのかは名前だけで分かるのがベストです。
マント さんが書きました:ここで質問なのですがgamemainでまだ定義されていない構造体が宣言されていますよね
これっていいのでしょうか?それともポインタだと特別なのでしょうか?
ポインタは特別です。
構造体サイズが分からなくても構造体名が決まっていればポインタは宣言が出来るようになっています。
ちなみに、私の書いたload()はmallocで書かずにstaticで書くことも可能です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マント

Re: キャラの構造体管理

#30

投稿記事 by マント » 14年前

なるほど、ポインタにはそういう特徴があったのですか…
調べてみたら名前の付け方にも暗黙のお約束があるようですね


charobjをmallocしてstaticと同じということは
xnum,ynum,animPtn,muki,*images;
構造体の中身に入っているこれら情報を保持できるということですよね


前から気になっていたのですが
mapmove.hには CHAR_OBJECT PlayerObj; こんな一文があります
おそらくCHAR_OBJECTっていうのはchar.hに書いてあるポインタのことだと思います
ですが、CHAR_OBJECTが指しているtag_CharObjectの中身は
mapmove.hから見えないと思うのですがどうして実体宣言できるのでしょうか?
またポインタは特別だとかそういうことでしょうか?


面倒くさい質問ばかりすいません

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#31

投稿記事 by softya(ソフト屋) » 14年前

CHAR_OBJECTはtypedefされた型名です。
// キャラ管理オブジェクト
typedef struct tag_CharObject *CHAR_OBJECT;
と定義して有りますので、struct tag_CharObject *と書くのとCHAR_OBJECTと書くのは同じという意味になります。
なので、
CHAR_OBJECT PlayerObj;

struct tag_CharObject *PlayerObj;
と書いているのと同じって事になりますね。つまりPlayerObjはポインタです。

【追記】
ちなみにchar.cpp以外のstruct tag_CharObjectはメンバが参照できないので「不完全型宣言」と言います。
PlayerObjも同様にメンバが参照ができないので「不透明ポインタ」と呼びます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マント

Re: キャラの構造体管理

#32

投稿記事 by マント » 14年前

ポインタってことは型が分からなくても宣言できる
前にソフト屋さんが教えてくれたおかげで理解できます

メンバが参照できないのにどうして存在しているのでしょうか?
型が分からないのになぜ使えるんですか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#33

投稿記事 by softya(ソフト屋) » 14年前

マント さんが書きました:メンバが参照できないのにどうして存在しているのでしょうか?
メモリを指しているのがポインタですから、メンバがあるか無いかはポインタ値を保持する分には関係の無い話です。
メモリ自体はstaticかmallocで確保されているなら、変数寿命により存在し続けます。
マント さんが書きました:型が分からないのになぜ使えるんですか?
型が分からないから、メンバ参照の出来ないポインタ値としてしか使えません。
それと普通のポインタと違って、ポインタの加算はできません。
PlayerObj++;とやるとエラーになります。
大きがわかりませんからね。
この制限はvoid*と同じです。

それとchar.cpp内ではstruct tag_CharObject の構造が定義されているから使えます。


自分で試すプログラムを書いてみてくださいね。いくら聞いても実感できないと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マント

Re: キャラの構造体管理

#34

投稿記事 by マント » 14年前

今はポインタを調べなおすために苦Cってとこを見ているのですが
どうしても今、分からないところをすぐに知りたいという欲が湧いてしまうので…

不完全宣言っていう言葉をいろいろと調べて回ったのですが
よく理解できません
例えばこのRPGのソースのこの不完全宣言はどのように使っている(役立っている)
のでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#35

投稿記事 by softya(ソフト屋) » 14年前

マント さんが書きました:不完全宣言っていう言葉をいろいろと調べて回ったのですが
よく理解できません
例えばこのRPGのソースのこの不完全宣言はどのように使っている(役立っている)
のでしょうか?
何度も書いてますが構造体メンバの隠蔽です。
隠蔽することで外部での書き換えを禁止しています。

PlayerObj->muki=0;をgamemain.cppで書くとエラーなります。
それは、PlayerObjポインタの指す構造体のメンバをgamemain.cppが知らないからです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マント

Re: キャラの構造体管理

#36

投稿記事 by マント » 14年前

何度も書かせてすいませんです

メンバ参照もできない、書き換えもできないのであれば
何に使うのかと思いまして

もしかしたら、メンバ参照という言葉の認識が間違っているかもしれないのですが
もしや、「値を書き換えることはできない、しかし、中身の値が何かを確かめることはできる」
ということでしょうか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#37

投稿記事 by softya(ソフト屋) » 14年前

gamemain.cppでは参照も書き換えも出来ませんがchar.cpp内では参照も書き換えも出来ます。
char_Draw()関数で描画してますよね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

マント

Re: キャラの構造体管理

#38

投稿記事 by マント » 14年前

なるほど、分かったようなわからんようなですね
両方、ポインタの存在は知っているけど実体は片方しか知らんと

でもやっぱり型が分からないのに代入ができるってのが不思議でなりません
(変数を宣言するときにintとかをつけずに宣言するのと同じに見えます)
Cの仕組みを知っていたら不思議なことでもないんでしょうけど

マント

Re: キャラの構造体管理

#39

投稿記事 by マント » 14年前

おっと忘れました

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: キャラの構造体管理

#40

投稿記事 by ISLe » 14年前

ポインタ型の変数に入ってる値を代入してるだけなので、ポインタが示す先の型の大きさは分からなくても問題ないのですよ。
その値が正しくオブジェクトを指していなかったとしても(不定の値)ただの値ですから。

封筒の中身を知らなくても配達できるのと同じようなものです。
int型は便箋に数値がそのまま書いてあるけど、ポインタ型はお宝の地図の書いてある便箋が入っています。
ポインタ変数に入るのは便箋であって、お宝ではありません。
関数呼び出しではコピーされた便箋が実引数に入って相手(関数側)に届きます。
不完全型は地図を読めないけど便箋のやりとりはできるというものです。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: キャラの構造体管理

#41

投稿記事 by softya(ソフト屋) » 14年前

アドレスは住所ですから、こう言う例えも出来るかと思います。
ポインタ変数=メモ
アドレス=住所
とします。

ポインタ=住所のメモですから、そこに何が建っているかは知らなくても問題はありません。
人(関数)に渡すことも出来ますし、保持することも出来ます。
ただ手紙を送るなら、構造体=ビルの部屋番号や入居者(メンバ)を知っている必要があります。
charさん(関数)はCHAR_OBJECTビルの入居者に手紙を送る担当なのでcharさんに住所のメモを渡せば適切に処理してくれます。
CHAR_OBJECT担当はない人(関数に)にCHAR_OBJECTビルの住所を渡しても適切には処理されません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

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