ページ 11

構造体を入れ子にすると、数値が???になります

Posted: 2013年1月02日(水) 15:56
by Butler
タイトル通りです。

関数内で入れ子を持つ構造体を作成したところ
数値が???となり数値の代入等(エラー報告は無し)ができません。

コード:

struct Sab1{
	int sd1,sd2,sd3;
};
struct Make{
	Sab1 d1;
}Data;
構造体作成後の数値はData.d1.sd1からData.d1.sd3まで全て???です

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月02日(水) 15:58
by nil
どのようにして数値を確認したのですか?
初期値は代入しましたか?

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月02日(水) 16:07
by Butler
数値の確認は実行中ブレークポイントを関数内に設定して確認をとりました。
初期値の代入も試みましたが、代入しても???になります。
また、この時エラー等の報告はありません。

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月02日(水) 16:21
by box
構造体の部分だけでなく、当該の現象が起きているコード全体を
見せていただくことは可能でしょうか。

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月02日(水) 16:33
by Butler
別の個所にて宣言してあるクラスです。

コード:

class SDataC{
private:

public:
	void SaveData();//セーブデータにセーブ
	void LoadData();//セーブデータのロード
}save;
こちらがセーブの関数です。
この関数の中で起こってます。

コード:

void SDataC::SaveData(){
	struct Sab1{
	    int sd1,sd2,sd3;
	};
	struct Make{
	    Sab1 d1;
	}Data;
}
ロードの方は空で、中身はまだ何も書いていません。

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月02日(水) 16:40
by box
何だかうまく意図が伝わっていないようです。
box さんが書きました:構造体の部分だけでなく、当該の現象が起きているコード全体を
見せていただくことは可能でしょうか。
このように書いたのは、main関数などを含めて、質問者さんのところで
当該の現象を確認された際のコード(回答しようとする側で、何も手を加えずに
コンパイル~実行ができるコード)を全部見せていただくことは可能でしょうか?
という意味です。

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月02日(水) 16:45
by ISLe
Butler さんが書きました:この関数の中で起こってます。
初期化しない一時変数は、構造体の入れ子であろうとなかろうと、さらに構造体であろうとなかろうと、初期値は不定ですけども。

どうやって値を確認したのかの手順を省略せずに記述していただくと良いかと。
同じ名前の外部変数があったりするとウォッチウィンドウでは混同する場合がありますから。

(追記)
考えたら値が不定でも(おそらくウォッチウィンドウの?)表示が???にはならないですね。
やはり別の識別子を参照している可能性が高いですね。

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月02日(水) 17:10
by Butler
単体で起動できる部分ですね、わかりました><

コード:

//メイン部分
#include "DxLib.h"
int winx=800,winy=600;

int Key[256]; // キーが押されているフレーム数を格納する

static int mStartTime;      //測定開始時刻
static int mCount;          //カウンタ
static float mFps;          //fps
static const int N = 60;	//平均を取るサンプル数
static const int FPS = 60;	//設定したFPS

int gpUpdateKey(){
	char tmpKey[256]; // 現在のキーの入力状態を格納する
	GetHitKeyStateAll( tmpKey ); // 全てのキーの入力状態を得る
	for( int i=0; i<256; i++ ){ 
		if( tmpKey[i] != 0 ){ // i番のキーコードに対応するキーが押されていたら
			Key[i]++;     // 加算
		} else {              // 押されていなければ
			Key[i] = 0;   // 0にする
		}
	}
	return 0;
}

bool Update(){
	if( mCount == 0 ){ //1フレーム目なら時刻を記憶
		mStartTime = GetNowCount();
	}
	if( mCount == N ){ //60フレーム目なら平均を計算する
		int t = GetNowCount();
		mFps = 1000.f/((t-mStartTime)/(float)N);
		mCount = 0;
		mStartTime = t;
	}
	mCount++;
	return true;
}
void Wait(){
	int tookTime = GetNowCount() - mStartTime;	//かかった時間
	int waitTime = mCount*1000/FPS - tookTime;	//待つべき時間
	if( waitTime > 0 ){
		Sleep(waitTime);	//待機
	}
}


//クラス
class SDataC{
private:

public:
	void SaveData();//セーブデータにセーブ
	void LoadData();//セーブデータのロード
}save;


int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
	//ウィンドウの生成
	ChangeWindowMode(TRUE); // ウィンドウモードに設定
	SetGraphMode(winx,winy, 16);
	//全体の初期化
	SetWaitVSyncFlag(FALSE);
	DxLib_Init();   // DXライブラリ初期化処理
	//fontset();//ここで各種文字フォントのセットをしています
	//メインループ
	while( ClearDrawScreen()==0 && gpUpdateKey()==0 ){
		Update();

		//ここで全ての動作・描画を行う
		//if (prog.AllLoop()==0) break;
		
		//セーブ実験のため、自分からセーブできるように
		//一時的にここに関数を置く
		if (Key[KEY_INPUT_X]==1) save.SaveData();
		
		if (ProcessMessage()==-1) break;
		ScreenFlip();
		Wait();
	}
	//終了動作
	DxLib_End();// DXライブラリ終了処理
	return 0;
}

//セーブ命令
void SDataC::SaveData(){
	struct Sab1{
		int sd1,sd2,sd3;
	};
	struct Make{
		Sab1 d1;
	}datafile;//先ほどのコードより少々変更されてます
}
//ロード命令
void SDataC::LoadData(){
	//ここにロード命令を書く
}
全体の動作・描画については少々長め&直接は関係してこないので載せていません。
fontset();とprog.AllLoop()がコメント化しているのは、実行しなくてもバグが起こるかどうかを確かめていたためです。

また、この状態でも同じようにバグが起こる事も確かめました。


>>ISLeさん
不定ではなく、利用不可能な数値が出されるみたいです。
初期化やメモリへのコピーもできません。

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月02日(水) 17:13
by Butler
>>ISLeさん
追記に気付けず返信してしまい申し訳ないです><

(追記)
ブレークポイントはセーブポイントのラスト、94においてます。

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月02日(水) 19:14
by nil
ISLeさんもおっしゃっていますが、初期値が代入されていない一時変数の値は不定です。
値を代入した上で、もう一度確認することはできますか。
あと、SDataC::SaveDataはどこから呼び出されるのですか?
boxさんの仰っている通り、
当該の現象を確認された際のコード(回答しようとする側で、何も手を加えずにコンパイル~実行ができるコード)
でなければ正確な再現ができません。

メインループの手前で、SaveDataを呼び出し、
更にSaveDataを以下のように改変したところ、出力から、構造体が初期化されていることを確認できました。

コード:

void SDataC::SaveData(){
    struct Sab1{
        int sd1,sd2,sd3;
    };
    struct Make{
        Sab1 d1;
	}datafile = { { 0,0,0 } };//先ほどのコードより少々変更されてます
	printfDx( L"%d\n%d\n%d\n", datafile.d1.sd1, datafile.d1.sd2, datafile.d1.sd3 );
//	DebugBreak();
}
DebugBreakした場合、確かに???と表示されましたが、その原因はわかりませんでした。

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月02日(水) 19:26
by box
涼雅 さんが書きました: あと、SDataC::SaveDataはどこから呼び出されるのですか?
75行目で呼び出しているようです。ただ、「どういう値をセーブしようとしているか」という
質問者さんの意思は見受けられないようです。

# ブレークポイントを入れる場所によっては、「???」となることがあるような気がする。
# 1行上に入れてみたら、どうなるだろう?

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月02日(水) 19:32
by へにっくす
ブレークした状態では表示できないのかもね。
無視した方がよさげ?

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月02日(水) 19:40
by Butler
>>涼雅さん

>>値を代入した上で、もう一度確認することはできますか。

ブレークをとらず数値を画面上に出した結果は0で初期化できていました。

ブレークを利用した際に数値を確認すると問題が生じるのはいまだ不明なのですね><

>>あと、SDataC::SaveDataはどこから呼び出されるのですか?

メインの上と下に分かれてはいますが、
クラスの宣言をメインよりも上にしてあるので
実行は出来るかと思います。

一応・・・
今回使用する構造体は代入して使うため、
初期化の必要はないと思ってます。
毎回初期化してると見えにくくなるため、
必要のない時は初期化してないのです


>>boxさん

>>どういう値をセーブしようとしているか

セーブについてはここまでで、まだ進めてないですね。
セーブするために利用する構造体を作ってみたところ、
このようなバグが起きてしまったため作業停止中です・・・

>># ブレークポイントを入れる場所によっては、「???」となることがあるような気がする。
>># 1行上に入れてみたら、どうなるだろう?

こちらについては全部の段(datafileが初期化された後の)にブレークポイントを置きましたが効果なしでした。

>>へにっくすさん
確認ありがとうございます!

無視して続行する以外にはないのでしょうかね・・・

できればこまめにブレークポイントを利用してバグがないか調べたかったのですがorz

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月03日(木) 01:29
by Ryo
構造体の宣言を、関数の外で行ってみてください

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月03日(木) 02:26
by ISLe
Visual Studio Express 2012 for Desktopだと表示されますね。

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月03日(木) 09:11
by Butler
>>Ryoさん
クラス内での構造体として使えば問題は起きませんでした。
>>ISLeさん
確認ありがとうございます!
2005、2010、2012で起こるということは
おそらくVisual Studioでは共通して起こる現象みたいですね・・・



関数用の構造体をクラスで宣言するのはあまり好みではないですが、
この状態でやっていくことにします。

ありがとうございました><

Re: 構造体を入れ子にすると、数値が???になります

Posted: 2013年1月03日(木) 17:19
by ISLe
Butler さんが書きました:2005、2010、2012で起こるということは
おそらくVisual Studioでは共通して起こる現象みたいですね・・・
すみません。曖昧な書き方でしたね。
2012では、きちんと値が表示されます。