ページ 11

アドレスを扱える型について

Posted: 2011年7月06日(水) 20:24
by 小人
ただ今再帰処理のプログラムの下地を作ろうとしているのですが、引数に構造体のアドレスを渡そうと思っています。

しかし普通に構造体のアドレスを渡し、それをポインタ型で受け取ってしまうと次の再帰関数の時にポインタのポインタ?(これで正しいのか自信ありません・・)の様にしなくてはならなくなり、これはアカンなと気付きました。

そこでアドレスを一旦何かに収納し、それを引数として渡し、関数内でその引数に対し

*構造体ポインタ名 = 引数

の様にして関数外の構造体にアクセスしようと考えました。


そのために構造体のアドレスをPrintfで調べた所整数だったため、int型でアドレスを扱おうとしたらエラーが出てしまいました。

元からこんな事出来ないのではないかという不安はあったのですが、やっぱり仕様上無理なのでしょうか・・・?
それともint型という選択がおかしかったのでしょうか。

少々分かり辛い質問になってしまい申し訳御座いません。

Re: アドレスを扱える型について

Posted: 2011年7月06日(水) 20:32
by h2so5
小人 さんが書きました:ただ今再帰処理のプログラムの下地を作ろうとしているのですが、引数に構造体のアドレスを渡そうと思っています。

しかし普通に構造体のアドレスを渡し、それをポインタ型で受け取ってしまうと次の再帰関数の時にポインタのポインタ?(これで正しいのか自信ありません・・)の様にしなくてはならなくなり、これはアカンなと気付きました。
何がしたいのかよく分からないのですが、
次の再帰関数の時も構造体のポインタで受け取るのは問題があるのですか?

Re: アドレスを扱える型について

Posted: 2011年7月06日(水) 20:34
by box
どんなコードを書いたのか教えてほしいです。

ポインターへのポインターへの…
という話と
再帰呼び出しのネストの話とは
全く別物です。

Re: アドレスを扱える型について

Posted: 2011年7月06日(水) 20:49
by softya(ソフト屋)
一度、再帰呼び出しコードをコンパクトにまとめた問題点再現のコードを書いてみてください。
ポインタのポインタなんてことには、ならないはずです。

Re: アドレスを扱える型について

Posted: 2011年7月06日(水) 20:52
by hidden
どんなプログラムを目指してどんな設計をしているのかはよく分かりませんが。
構造体のアドレスを扱うのはint型ではなく構造体へのポインタ型ですね。

引数に構造体へのポインタを持つ再帰関数であれば
その関数のなかで自身を呼ぶときの引数は受け取ったポインタをインクリメントをしたポインタあたりになるのかなー
などと思います。 どんなコードかわからないままでの想像ではありますけど。

Re: アドレスを扱える型について

Posted: 2011年7月06日(水) 20:59
by 小人
すみません、予想以上に訳の分からない質問になってしまいました。

一旦こちらの質問は解決とさせて頂き、しかるべき質問の場所(オセロの所)にソースコードを添付したいと思いますので暫しお待ちして頂いても宜しいでしょうか?
(自分で適当に書いていたのでソースコード内がぐちゃぐちゃでコメント皆無なため)

Re: アドレスを扱える型について

Posted: 2011年7月06日(水) 21:00
by softya(ソフト屋)
小人 さんが書きました:すみません、予想以上に訳の分からない質問になってしまいました。

一旦こちらの質問は解決とさせて頂き、しかるべき質問の場所(オセロの所)にソースコードを添付したいと思いますので暫しお待ちして頂いても宜しいでしょうか?
(自分で適当に書いていたのでソースコード内がぐちゃぐちゃでコメント皆無なため)
オセロでは無く、コンパクトなテストコードを書いたほうが良いと思います。
プログラミングで悩んだら、切り離した研究・テストコードを作るのは非常に良い方法ですよ。

Re: アドレスを扱える型について

Posted: 2011年7月06日(水) 21:05
by 小人
丁度今そう思い直しました。
オセロのコードを載せても他の方が困惑するだけでしょうし、ちょっとテストコードを作ってみますm(_ _)m

Re: アドレスを扱える型について

Posted: 2011年7月06日(水) 22:09
by 小人
100までの数の内、2で割り切れる数をカウントするプログラムを組んでみました。(こんなの再帰も構造体も使う必要無いですけれど・・・)


まずは理想の形

コード:

#include<stdio.h>

//構造体の定義
typedef struct test_struct{
	int count;			//割り切れた回数を収納しておく変数
}test_struct;

//関数のプロトタイプ宣言
void Recursive(test_struct *test_p);

//メイン関数
int Main(void){
	test_struct test ={0};			//構造体変数の初期化
	Recursive(&test);				//再帰関数呼び出し
	printf("アドレス:%d\n",&test);
	return 0;
}

//1から100までの数の内、2で割り切れる個数を求める再帰関数
void Recursive(test_struct *test_p){
	int number = 0;					//整数を扱う変数の初期化

	for(number = 1; number < 101; number++){
		if( (number % 2) == 0){				//2で割り切れるならcountの値を1つ増やして再帰
			test_p->count += 1;
			Recursive(&test_p);
		}
	}
}
これだと再帰関数内のRecursiveの引数でエラーが。
引数を本当は &test にしたいのですが、これは再帰内で定義していませんから使えず・・・。


そして次がどうにかこのエラーを打開しようと無理して作った代物

コード:

#include<stdio.h>

//構造体の定義
typedef struct test_struct{
	int count;			//割り切れた回数を収納しておく変数
}test_struct;

//関数のプロトタイプ宣言
void Recursive(int);

//メイン関数
int Main(void){
	test_struct test ={0};			//構造体変数testの初期化

	int address_test = &test;		//構造体変数testのアドレスの数値を保存

	Recursive(address_test);				//再帰関数呼び出し
	printf("アドレス:%d\n",&test);
	return 0;
}

//1から100までの数の内、2で割り切れる個数を求める再帰関数
void Recursive(int address_test){
	int number = 0;					//整数を扱う変数の初期化

	test_struct *test_p = address_test;		//受け取ったアドレスの数値をポインタ先に選択

	for(number = 1; number < 101; number++){
		if( (number % 2) == 0){				//2で割り切れるならcountの値を1つ増やして再帰
			test_p->count += 1;
			Recursive(address_test);
		}
	}
}
薄々気付いてましたがやっぱり駄目でしたorz

Re: アドレスを扱える型について

Posted: 2011年7月06日(水) 22:17
by 小人
あ、このソースコードだと再帰するたびに0からになる事に今気付きました。

削除はご法度との事なので、修正するまで上のコードはスルーしてあげて下さいm(_ _)m

Re: アドレスを扱える型について

Posted: 2011年7月06日(水) 22:20
by h2so5
test_pはポインタなので、

Recursive(test_p);

でいいのでは?

Re: アドレスを扱える型について

Posted: 2011年7月06日(水) 22:51
by 小人
このような形で宜しいでしょうか?

コード:

#include <stdio.h>

//構造体の定義
typedef struct test_struct{
	int number;			//整数を扱う変数
	int count;			//割り切れた回数を収納しておく変数
}test_struct;

//関数のプロトタイプ宣言
void Recursive(test_struct *test_p);

//メイン関数
int Main(void){
	test_struct test ={0,0};			//構造体変数の初期化
	Recursive(&test);				//再帰関数呼び出し
	printf("アドレス:%d\n",&test);
	return 0;
}

//0から100までの数の内、2で割り切れる個数を求める再帰関数
void Recursive(test_struct *test_p){

	for(; test_p->number < 101; test_p->number++){
		if( (test_p->number % 2) == 0){				//2で割り切れるならcountの値を1つ増やして再帰
			test_p->count += 1;
			Recursive(test_p);
		}
	}
}
何故かソースコードとは関係の無いエラーが起きてしまい、解決出来ず結果が試せないのですorz

コンソールアプリケーションを選択し、プロジェクトのコード生成でMDdに変更したのに未解決のシンボル云々が・・・。

Re: アドレスを扱える型について

Posted: 2011年7月06日(水) 22:59
by 小人
あぁ
int Main
ではなく
int main

でした。
最近 WinMainばかりでしたのでごっちゃになってましたorz

しかし実行した所強制終了してしまいました。
無限ループにはならないと思うのですが・・・何故でしょう。。

ちょっと修正

コード:

#include <stdio.h>

//構造体の定義
typedef struct test_struct{
	int number;			//整数を扱う変数
	int count;			//割り切れた回数を収納しておく変数
}test_struct;

//関数のプロトタイプ宣言
void Recursive(test_struct *test_p);

//メイン関数
int main(void){
	test_struct test ={0,0};			//構造体変数の初期化
	Recursive(&test);				//再帰関数呼び出し
	printf("アドレス:%d\n",&test);
	return 0;
}

//0から100までの数の内、2で割り切れる個数を求める再帰関数
void Recursive(test_struct *test_p){

	for( ; test_p->number < 101; test_p->number += 1){
		if( (test_p->number % 2) == 0){				//2で割り切れるならcountの値を1つ増やして再帰
			test_p->count += 1;
		}
		Recursive(test_p);
	}
}

Re: アドレスを扱える型について

Posted: 2011年7月06日(水) 23:14
by softya(ソフト屋)
デバッガで実行すればエラーの種類がわかるはずですが?

[追記]
>しかし実行した所強制終了してしまいました。
>無限ループにはならないと思うのですが・・・何故でしょう。。

思い込みは、原因追及の妨げにしか成らないのでプログラムに必ず原因があります。
どうしたら原因がつかめるか工夫してみましょう。

Re: アドレスを扱える型について

Posted: 2011年7月06日(水) 23:46
by 小人
>ソフト屋さん
お陰で原因は判明しました
再帰関数内の再帰呼び出し手前で

コード:

printf("現在の値 number:%d count:%d\n",test_p->number,test_p->count);
を追加するとnumberの値が加算されてないために延々再帰されてスタックオーバーフローになっとりました。

しかし何故numberの値が増えてくれないのかが分かりません・・・orz
prindtfで値が参照出来ているという事は再帰内から構造体にしっかりアクセスは出来ている訳ですから、ちゃんとnumberも加算・・・あ、。

出来ました。
そうでした、for文は三番目の式が行われるのは最後だから今までのじゃアカンかったんですね・・・。

コード:

#include <stdio.h>

//構造体の定義
typedef struct test_struct{
	int number;			//整数を扱う変数
	int count;			//割り切れた回数を収納しておく変数
}test_struct;

//関数のプロトタイプ宣言
void Recursive(test_struct *test_p);

//メイン関数
int main(void){
	test_struct test ={1,0};			//構造体変数の初期化
	Recursive(&test);				//再帰関数呼び出し
	printf("アドレス:%d\n",&test);
	printf("解答:%d\n",test.count);
	return 0;
}

//1から100までの数の内、2で割り切れる個数を求める再帰関数
void Recursive(test_struct *test_p){

	for( ; test_p->number < 101; ){
		if( (test_p->number % 2) == 0){				//2で割り切れるならcountの値を1つ増やして再帰
			test_p->count += 1;
		}
		printf("現在の値 number:%d count:%d\n",test_p->number,test_p->count);
		test_p->number += 1;
		Recursive(test_p);
	}
}
これで解決とさせて頂きます。
皆様付き合って下さって有難う御座いましたm(_ _)m