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

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
小人
記事: 78
登録日時: 14年前

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

#1

投稿記事 by 小人 » 14年前

ただ今再帰処理のプログラムの下地を作ろうとしているのですが、引数に構造体のアドレスを渡そうと思っています。

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

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

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

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


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

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

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

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

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

#2

投稿記事 by h2so5 » 14年前

小人 さんが書きました:ただ今再帰処理のプログラムの下地を作ろうとしているのですが、引数に構造体のアドレスを渡そうと思っています。

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

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

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

#3

投稿記事 by box » 14年前

どんなコードを書いたのか教えてほしいです。

ポインターへのポインターへの…
という話と
再帰呼び出しのネストの話とは
全く別物です。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

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

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

#4

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

一度、再帰呼び出しコードをコンパクトにまとめた問題点再現のコードを書いてみてください。
ポインタのポインタなんてことには、ならないはずです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

hidden

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

#5

投稿記事 by hidden » 14年前

どんなプログラムを目指してどんな設計をしているのかはよく分かりませんが。
構造体のアドレスを扱うのはint型ではなく構造体へのポインタ型ですね。

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

小人
記事: 78
登録日時: 14年前

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

#6

投稿記事 by 小人 » 14年前

すみません、予想以上に訳の分からない質問になってしまいました。

一旦こちらの質問は解決とさせて頂き、しかるべき質問の場所(オセロの所)にソースコードを添付したいと思いますので暫しお待ちして頂いても宜しいでしょうか?
(自分で適当に書いていたのでソースコード内がぐちゃぐちゃでコメント皆無なため)
最後に編集したユーザー 小人 on 2011年7月06日(水) 21:04 [ 編集 1 回目 ]

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

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

#7

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

小人 さんが書きました:すみません、予想以上に訳の分からない質問になってしまいました。

一旦こちらの質問は解決とさせて頂き、しかるべき質問の場所(オセロの所)にソースコードを添付したいと思いますので暫しお待ちして頂いても宜しいでしょうか?
(自分で適当に書いていたのでソースコード内がぐちゃぐちゃでコメント皆無なため)
オセロでは無く、コンパクトなテストコードを書いたほうが良いと思います。
プログラミングで悩んだら、切り離した研究・テストコードを作るのは非常に良い方法ですよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

小人
記事: 78
登録日時: 14年前

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

#8

投稿記事 by 小人 » 14年前

丁度今そう思い直しました。
オセロのコードを載せても他の方が困惑するだけでしょうし、ちょっとテストコードを作ってみますm(_ _)m

小人
記事: 78
登録日時: 14年前

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

#9

投稿記事 by 小人 » 14年前

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

小人
記事: 78
登録日時: 14年前

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

#10

投稿記事 by 小人 » 14年前

あ、このソースコードだと再帰するたびに0からになる事に今気付きました。

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

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

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

#11

投稿記事 by h2so5 » 14年前

test_pはポインタなので、

Recursive(test_p);

でいいのでは?

小人
記事: 78
登録日時: 14年前

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

#12

投稿記事 by 小人 » 14年前

このような形で宜しいでしょうか?

コード:

#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に変更したのに未解決のシンボル云々が・・・。

小人
記事: 78
登録日時: 14年前

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

#13

投稿記事 by 小人 » 14年前

あぁ
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);
	}
}

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

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

#14

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

デバッガで実行すればエラーの種類がわかるはずですが?

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

思い込みは、原因追及の妨げにしか成らないのでプログラムに必ず原因があります。
どうしたら原因がつかめるか工夫してみましょう。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

小人
記事: 78
登録日時: 14年前

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

#15

投稿記事 by 小人 » 14年前

>ソフト屋さん
お陰で原因は判明しました
再帰関数内の再帰呼び出し手前で

コード:

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

閉鎖

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