ページ 11

ポインタが分かりません

Posted: 2008年4月03日(木) 11:56
by そら
ポインタが苦手で、解決法が分かりません。
どなたか、力を貸して下さい。

以下、サンプルです。

#include "stdio.h"
#include "string.h"

typedef struct {
    int     a;
    int     b;
    char    c[32];
} DATA_T;

void Code001();
void Code002();
int  Code003(DATA_T *tData1, DATA_T *tData2);

DATA_T  tData[10];

void Code001()
{
    int     i;
    
    memset(&tData, 0, sizeof(tData));
    for(i=0;i<5;i++){
        tData[0].a = 1;
    }
    
    return;
}
void Code002()
{
    DATA_T  *tData1 = NULL;
    
    if( 0 == Code003(tData1, &tData[0]) ){
        printf("1-%08x\n", tData1);
        printf("2-%08x\n", &tData);     // ---(1)
    }
    
    return;
}
int Code003(DATA_T *tData1, DATA_T *tData2)
{
    int     i;
    
    for(i=0;i<10;i++){                  // ---(2)
        if( tData2->a == 0 ){
            tData1 = tData2;            // ---(3)
            return (0);
        }
		tData2++;
    }
    
    return (1);
}
int main(int argc, char* argv[/url])
{
    char    aaa[64];
    
    Code001();
    Code002();
    
    printf("おしまい: ");
    scanf("%s", aaa);
    
    return 0;
}

分からないこと
1. (1)で、(3)のときの tData1 のアドレスが返らない(NULLのまま)
2. (2)で、10ではなく配列数を動的に取りたい

以上、よろしくお願いします。

Re:ポインタが分かりません

Posted: 2008年4月03日(木) 12:30
by tk-xleader
(2)malloc関数を使ってください。使い方は…

型 *p;
p=malloc(確保したい要素数*sizeof(型));
使い終わったら…
free(p);

とします。
(1)まず、(tData2->a == 0)の結果が偽ですから、その中の文は実行されませんし、関数にアドレスを渡しているわけですが、[color=White" size="6">アドレスは値[/color]なので、[color=White" size="6]書き換えても、それはコピーを書き換えた事になる[/color]のです。
つまり、元の変数のアドレスが変わることはありません。そもそも、変数のアドレスはコロコロ変わったりしません。

Re:ポインタが分かりません

Posted: 2008年4月03日(木) 15:05
by やそ
流れを追うと
---------------------------

DATA_Tという構造体を定義した。
DATA_T型の配列 tData[10];を定義した。

void Code001()
では値の代入を行っている。戻り値はなし。
( tData[0].a = 1;なのでforでループさせたところで、[0]にしか代入していないが・・・)


void Code002()
{
DATA_T *tData1 = NULL;

(ポインタを宣言しているにも関わらず、代入する値(アドレス)がNULLって・・・メモリを破壊したいのでしょうか?)

if( 0 == Code003(tData1, &tData[0]) ){
printf("1-%08x\n", tData1);
printf("2-%08x\n", &tData); // ---(1)
}
Code003の戻り値が0の時に実施させると言うif文自体は問題なさそうですね。
ただ、Code003の第一引数がtData1なのでNULLが渡されることになりますね・・・。

int Code003の関数では・・・
tData2->a == 0は必ず偽を返します。
なぜなら、Code001で
tData[0].a = 1;
としているからです。
なので戻り値は
return (1);
を返し、結果、Code002のif文は必ず偽になり、printf文は実行されません。
また、main関数のコマンドライン引数とか、scanfとか全く意味を成さないように見えますが???

Re:ポインタが分かりません

Posted: 2008年4月03日(木) 15:33
by そら
回答有難う御座います。

> アドレスは値なので、書き換えても、それはコピーを書き換えた事になるのです
DATA_T *Code003(int index, DATA_T *tData2);
とかでしか、ポインタは返せないのかな・・・

> ( tData[0].a = 1;なのでforでループさせたところで、[0]にしか代入していないが・・・)
気付かなかった。
tData.a = 1;
の間違い

> (ポインタを宣言しているにも関わらず、代入する値(アドレス)がNULLって・・・メモリを破壊したいのでしょうか?)
理解不足ですね。
とりあえず何でも空にしようとするので・・・

> tData2->a == 0は必ず偽を返します。 
そんなことはないと思うけど・・・。
tData2++;
で、実質 tData.a を参照できてるはず。

> main関数のコマンドライン引数とか、scanfとか全く意味を成さないように見えますが??? 
実行確認用。



Code003を汎用化して
    DATA_T  tDataA[10];
    DATA_T  tDataB[20];
    DATA_T  tDataC[30];
とかから検索させたかったけども無理そうだ。

int  Code003(int *index, DATA_T *tData2);

if( 0 == Code003(&index, &tData[0]) ){
    tData1 = &tData[index];

的な逃げ方しかないのかな・・・。
1手間増えるけど。

Re:ポインタが分かりません

Posted: 2008年4月03日(木) 17:02
by バグ
アドレスを代入させたい変数にポインタのポインタを利用すればいけるはずですよ。
ちょっとややこしくなるかもしれませんけど…
void Code002()
{
    DATA_T* pData1 = NULL;
	if (Code003(&pData1, &tData[0]) == 0)
	{
		if (pData1 != NULL)
		{
			printf("1-%08x\n", pData1);
			printf("2-%08x\n", tData); 
		}
	}
}

int Code003(DATA_T** ppData1, DATA_T* pData2)
{
	int i;

	for (i = 0; i < 10; i++)
	{
		if (pData2->a == 0)
		{
			*ppData1 = pData2;			// ---(3)
			return 0;
		}

		pData2++;
	}

	return 1;
}

Re:ポインタが分かりません

Posted: 2008年4月03日(木) 17:04
by バグ
おっと、書き忘れていましたが、個人的な趣味の話になりますが、Code003関数に関しては、下記のような書き方の方が個人的には好きですね。まぁ、参考程度に…という事で(^_^;)
int Code003(DATA_T** ppData1, DATA_T* pData2)
{
	int i;

	for (i = 0; i < 10; i++)
	{
		if ((pData2 + i)->a == 0)
		{
			*ppData1 = (pData2 + i);			// ---(3)
			return 0;
		}
	}

	return 1;
}

Re:ポインタが分かりません

Posted: 2008年4月03日(木) 17:44
by そら
> バグさん
欲しかったアドレスが返って来ました。
有難う御座いました。

(2)については、

int Code003(DATA_T** ppData1, DATA_T* pData2, int num);

if (Code003(&pData1, &tData[0], sizeof(tData)/sizeof(DATA_T)) == 0)

で、要素数も引数に混ぜます。
さすがにポインタから要素数を求めるのは無理か・・・

Re:ポインタが分かりません

Posted: 2008年4月03日(木) 22:54
by バグ
要素数に関しては、静的に確保するにしろ、動的に確保するにしろ、プログラマ側が管理してやらなければいけない領域だと思います。ですから、毎回要素数を求めるよりは、定数なり変数なりで保持しておいた方が使い勝手のよい関数になると思いますよ。

敵の描画について

Posted: 2008年4月20日(日) 09:32
by SONY
 こんにちは。シューティングゲームの館で勉強している者です。今、敵の描画をアニメーションでやっているのですが、どういうわけか、敵が点滅しながら登場します。
 プログラム自体は館のものをパクリながら作っています。これは、デフォルトで点滅するものなのでしょうか?

追記:敵の描画について

Posted: 2008年4月20日(日) 09:43
by SONY
先ほどの質問の追加ですが、アニメーションにしなければ点滅は起こりませんでした。

Re:追記:敵の描画について

Posted: 2008年4月20日(日) 11:59
by 管理人
>敵の描画をアニメーションでやっている

というのはどういうことでしょうか?
また、何節の話ですか?
プロジェクトのダウンロードで全てダウンロードしても、不具合が起きますか?

Re:追記:敵の描画について

Posted: 2008年4月26日(土) 14:46
by SONY
シューティングゲームの館 12節のところです。

Re:追記:敵の描画について

Posted: 2008年4月26日(土) 15:09
by 管理人
プロジェクトのダウンロードで全てダウンロードしても、不具合が起きますか?

Re:追記:敵の描画について

Posted: 2008年4月26日(土) 16:07
by SONY
鈍くさい質問ですいません。プロジェクトのダンロードで全てダウンロードするとはどういう意味ですか?

Re:追記:敵の描画について

Posted: 2008年4月26日(土) 20:22
by 管理人
シューティングゲームの館http://dixq.net/s/
ソースとプロジェクトのダウンロード(その1)

ソースとプロジェクトのダウンロード(その2)
がありますよね。プロジェクトが丸ごとダウンロード出来ますので、
ここから使用していただけるとコピーミスやコードのミスなどがありません。

Re:追記:敵の描画について

Posted: 2008年4月27日(日) 20:52
by SONY
ありがとうございました。問題は解決しました。しかし、また新たな問題が発生しました。それは、シューティングゲームの館13節の敵を5枚の画像を時間差で表示して表現するというところです。
具体的にはプログラムを実行すると時が点滅します。
プログラム自体はサンプルをまねています。
開発環境はBCC Developerを使っています。
アドバイスよろしくお願いします。

Re:追記:敵の描画について

Posted: 2008年4月29日(火) 12:22
by SONY
計算の値を変更したらちゃんと動作しました。どうやら処理が間に合わなくて点滅していたようです。今まで私の質問に答えてくれた皆様、本当にありがとうございました。