トップページ > 過去ログ > 記事閲覧
構造体について
名前:mantis 日時: 2008/04/26 10:10

グローバル宣言した構造体のメンバ変数を違う関数内で書き換えたら、戻った瞬間に前の数値に戻ってしまいました。どうしたら違う関数内でメンバ変数の値を変えて、戻ってもその数値が使えるようにできるのでしょうか。教えて下さい。

Page: 1 |

Re: 構造体について ( No.1 )
名前:かたぱると 日時:2008/04/26 17:52

複数スレッドとかで相互に更新等を行っていたりしない限りは 関数内で変更したグローバル変数が元に戻る等は無いはずですが…。 メモリアクセスで壊していたり 自身で元の値に戻している等はありませんか? とりあえず基本形のコードを書いてみました。 検証にお役立てください。 以下をコピー #include "DxLib.h" // 構造体を定義 struct TestStruct { int pointA; int pointB; int pointC; }; // グローバル構造体を定義 TestStruct g_Struct; // 関数プロトタイプ宣言 void structUpdate_A( void ); void structUpdate_B( void ); int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ChangeWindowMode( TRUE ); if( DxLib_Init() == -1 ) // DXライブラリ初期化処理 { return -1; // エラーが起きたら直ちに終了 } ClearDrawScreen(); // グローバル構造体のメンバ変数を初期化する g_Struct.pointA = 0; g_Struct.pointB = 0; g_Struct.pointC = 0; // 内容表示 DrawFormatString( 10, 10 , GetColor(255,255,255) , "[default] pointA :%d pointB :%d pointC :%d" , g_Struct.pointA , g_Struct.pointB , g_Struct.pointC ); WaitKey() ; // キーの入力待ち((7-3)『WaitKey』を使用) // 内容変更 structUpdate_A(); DrawFormatString( 10, 30 , GetColor(255,255,255) , "[structUpdate_A] pointA :%d pointB :%d pointC :%d" , g_Struct.pointA , g_Struct.pointB , g_Struct.pointC ); WaitKey() ; // キーの入力待ち((7-3)『WaitKey』を使用) // 内容変更 structUpdate_B(); DrawFormatString( 10, 50 , GetColor(255,255,255) , "[structUpdate_B] pointA :%d pointB :%d pointC :%d" , g_Struct.pointA , g_Struct.pointB , g_Struct.pointC ); WaitKey() ; // キーの入力待ち((7-3)『WaitKey』を使用) DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 } void structUpdate_A( void ) { // グローバル構造体の中身を更新 g_Struct.pointA = 100; g_Struct.pointB = 200; g_Struct.pointC = 300; } void structUpdate_B( void ) { g_Struct.pointA = 456; g_Struct.pointB = 789; g_Struct.pointC = 12345; }
Re: 構造体について ( No.2 )
名前:mantis 日時:2008/04/26 21:01

調べてみたところ、 変数の宣言は問題ありませんでした。 int teki(data a,data b,data c)と、 int bunki(data a,data b,data c)、 int sentou(data a,data b,data c)の3つで戦闘判定をするのですが、 sentou(t1,t2,t3)の中で、 ↓ battle(t1,t2,t3)をよびだし、 ↓ teki(t1,t2,t3)でダメージ計算をし、 sentouへ戻るときに数値が元に戻ってしまいます。 なので、t1などが関数を進んでいく途中で違うものと認識されているのかもしれないですがどうでしょうか。
Re: 構造体について ( No.3 )
名前:かたぱると 日時:2008/04/27 00:20

成程納得。 teki,bunki,sentouの引数がグローバル変数自体を渡しており、 その状態だと問題の現象がおきます。 引数の内容を更新させたいのであればその引数のポインタを渡すべきです。 以下をコピー #include "DxLib.h" // 構造体を定義 struct TestStruct { int pointA; int pointB; int pointC; }; // グローバル構造体を定義 TestStruct g_Struct_1; TestStruct g_Struct_2; TestStruct g_Struct_3; // 表示用 int g_line; // 関数プロトタイプ宣言 void teki( TestStruct *data_1 , TestStruct *data_2 , TestStruct *data_3 ); void bunki( TestStruct *data_1 , TestStruct *data_2 , TestStruct *data_3 ); void sentou( TestStruct *data_1 , TestStruct *data_2 , TestStruct *data_3 ); void previewData( char *str ); int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ChangeWindowMode( TRUE ); if( DxLib_Init() == -1 ) // DXライブラリ初期化処理 { return -1; // エラーが起きたら直ちに終了 } ClearDrawScreen(); g_line = 0; // グローバル構造体のメンバ変数を初期化する g_Struct_1.pointA = 0; g_Struct_1.pointB = 0; g_Struct_1.pointC = 0; g_Struct_2.pointA = 0; g_Struct_2.pointB = 0; g_Struct_2.pointC = 0; g_Struct_3.pointA = 0; g_Struct_3.pointB = 0; g_Struct_3.pointC = 0; ClearDrawScreen(); // 内容表示 previewData( "最初" ); // 処理 teki( &g_Struct_1 , &g_Struct_2 , &g_Struct_3 ); // 戻ってきたので内容表示 previewData( "最後" ); DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 } void teki( TestStruct *data_1 , TestStruct *data_2 , TestStruct *data_3 ) { // 情報変更 data_1->pointA = 1; data_1->pointB = 2; data_1->pointC = 3; data_2->pointA = 4; data_2->pointB = 5; data_2->pointC = 6; data_3->pointA = 7; data_3->pointB = 8; data_3->pointC = 9; previewData( "teki-1" ); bunki( data_1 , data_2 , data_3 ); previewData( "teki-2" ); } void bunki( TestStruct *data_1 , TestStruct *data_2 , TestStruct *data_3 ) { // 情報変更 data_1->pointA = 10; data_1->pointB = 20; data_1->pointC = 30; data_2->pointA = 40; data_2->pointB = 50; data_2->pointC = 60; data_3->pointA = 70; data_3->pointB = 80; data_3->pointC = 90; previewData( "bunki-1" ); sentou( data_1 , data_2 , data_3 ); previewData( "bunki-2" ); } void sentou( TestStruct *data_1 , TestStruct *data_2 , TestStruct *data_3 ) { // 情報変更 data_1->pointA = 100; data_1->pointB = 200; data_1->pointC = 300; data_2->pointA = 400; data_2->pointB = 500; data_2->pointC = 600; data_3->pointA = 700; data_3->pointB = 800; data_3->pointC = 900; previewData( "sentou" ); } // いちいち書くのが面倒くさいので表示用関数 void previewData( char *str ) { DrawFormatString( 5, 16*g_line , GetColor(255,255,255) , "%s:1[A:%d/B:%d/C:%d] 2[A:%d/B:%d/C:%d] 3[A:%d/B:%d/C:%d]" , str , g_Struct_1.pointA , g_Struct_1.pointB , g_Struct_1.pointC , g_Struct_2.pointA , g_Struct_2.pointB , g_Struct_2.pointC , g_Struct_3.pointA , g_Struct_3.pointB , g_Struct_3.pointC ); WaitKey(); // キーの入力待ち((7-3)『WaitKey』を使用) g_line++; }
Re: 構造体について ( No.4 )
名前:キーチック 日時:2008/04/27 00:23

よく分からないけど,グローバル変数を関数呼び出しで引数として 受け渡してるのですか? グローバルなら,いちいち関数内部で宣言したりデータ渡したり しなくても,いきなり使えるはずですが…(構造体だと違うという ことではなかったと思いますが) むしろ宣言したことで,グローバル変数と同じ名前のローカル変数が 作られている可能性があるのではないかと思うのですがどうでしょうか
Re: 構造体について ( No.5 )
名前:mantis 日時:2008/04/27 07:48

アドバイスありがとうございます。 構造体をポインタで渡すようにしてみましたが、 . または .* の左側に構造体が必要(関数 battlegamen(int,data *,data *,data *) というエラーがでました。 ポインタにしたら.ではなくて->を使わないといけないということですか?
Re: 構造体について ( No.6 )
名前:かたぱると 日時:2008/04/27 23:44

説明が足らなかったですね、申し訳ない。 値そのものを渡すメソッドの引数はローカルコピーされたものなので いくら変更をしようとメソッドを抜けるとなくなってしまいます。 よって、呼び出した側はコピーを渡しているので当然変化無し。 ポインタで渡せば直接編集できるために変化が適用されます。 ポインタのアクセスにはアロー演算子『->』を使います。 このあたりは番外編「C言語のポインタの説明」を見ると触りが書いてあります。 ttp://homepage2.nifty.com/natupaji/DxLib/lecture/lectureOthers1.html んでアドレスを表示するのを組んでみました。 概念がわかるんじゃないかと。 以下をコピー #include "DxLib.h" // 構造体を定義 struct TestStruct { int pointA; int pointB; int pointC; }; // グローバル構造体を定義 TestStruct g_Struct_1; TestStruct g_Struct_2; TestStruct g_Struct_3; // 表示用 int g_line; // 関数プロトタイプ宣言 void func_A( TestStruct data_1 , TestStruct data_2 , TestStruct data_3 ); void func_B( TestStruct *data_1 , TestStruct *data_2 , TestStruct *data_3 ); void previewData( char *str , TestStruct *data1 , TestStruct *data2 , TestStruct * data3 ); int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { ChangeWindowMode( TRUE ); if( DxLib_Init() == -1 ) // DXライブラリ初期化処理 { return -1; // エラーが起きたら直ちに終了 } ClearDrawScreen(); SetFontSize( 12 ); g_line = 0; // グローバル構造体のメンバ変数を初期化する g_Struct_1.pointA = 0; g_Struct_1.pointB = 0; g_Struct_1.pointC = 0; g_Struct_2.pointA = 0; g_Struct_2.pointB = 0; g_Struct_2.pointC = 0; g_Struct_3.pointA = 0; g_Struct_3.pointB = 0; g_Struct_3.pointC = 0; ClearDrawScreen(); // 内容表示 // このアドレスが本物のグローバル変数を指し示すアドレス previewData( "グローバル:本物" , &g_Struct_1 , &g_Struct_2 , &g_Struct_3 ); // 処理 func_A( g_Struct_1 , g_Struct_2 , g_Struct_3 ); //!< 構造体自体を渡すメソッド func_B( &g_Struct_1 , &g_Struct_2 , &g_Struct_3 ); //!< 引数のポインタを渡すメソッド DxLib_End() ; // DXライブラリ使用の終了処理 return 0 ; // ソフトの終了 } void func_A( TestStruct data_1 , TestStruct data_2 , TestStruct data_3 ) { // このメソッドの引数はローカルにコピーされたものなので // このメソッドを抜けると無くなる。 // よってこのメソッド内でいくら変更してもなくなってしまう // 引数のアドレスがグローバルアドレスと違う事に注意 previewData( "直渡し:ローカル、偽者" , &data_1, &data_2 , &data_3 ); } void func_B( TestStruct *data_1 , TestStruct *data_2 , TestStruct *data_3 ) { // 渡されたアドレスはグローバルにある構造体を指しているので // ポインタアクセスでグローバルの構造体を直接編集する。 // よってこのメソッドを抜けてもグローバルの構造体を直接編集したため // 値が変更されている。 // 引数はポインタなのでグローバル変数のアドレス previewData( "ポインタ渡し:グローバル、本物" , data_1, data_2 , data_3 ); } // いちいち書くのが面倒くさいので表示用関数 void previewData( char *str , TestStruct *data1 , TestStruct *data2 , TestStruct *data3 ) { DrawFormatString( 5, 16*g_line , GetColor(255,255,255) , "%s:data1[%d] data2[%d] data3[%d]" ,str , data1 , data2 , data3 ) ; WaitKey(); // キーの入力待ち((7-3)『WaitKey』を使用) g_line++; }
Re: 構造体について ( No.7 )
名前:mantis 日時:2008/04/27 20:25

ありがとうございました! なんとかRPGの戦闘画面の処理を作ることができました! あとは同じモンスターが一度にダメージを受けるところを修正するのみです。

Page: 1 |