ポインタはまだよくわかってないですが…

アバター
annojyou
記事: 0
登録日時: 11年前
住所: 大阪

ポインタはまだよくわかってないですが…

投稿記事 by annojyou » 11年前

C言語何でも質問掲示板の方でちょっと気になった投稿があったので…。
http://dixq.net/forum/viewtopic.php?f=3&t=14855

投稿者さんもポインタで躓いているようだったのでちょっと覗いてみたんです。

まずポインタ変数を宣言していないのはどうなんでしょうか…。

void PLAYER::GetPosition(double *x,double *y){
*x=this->x;
*y=this->y;
//DrawFormatString(50,50,GetColor(255,255,255),"player差出座標(%f,%f)",this->x,this->y);
}

おそらくこの部分でポインタ変数を宣言した…ということなのかもしれませんが、これで行けたっけなぁ…とちょっと困惑気味だったり。void PLAYER::GetPositionより外側に取ってきたい変数があったとしたらこれはうまく機能してくれるのか?と、思ったり。
まあ、勉強中の身なので間違った点で見ているかもしれないので、おとなしく解決になるまで見守ろうかと思います。(ついでに私も勉強させてもらおう…)

…でも、何の意図があって自機の現在の座標が必要になったのかちょっとよくわからなかったです。(ポインタにすることで何か利点があるのか?)
ピチューンしたら初期位置に戻る方式なら別に現在の位置は必要ないと思ったんですが…リトライで同じ位置から復活したいのか?とも考えたけど…リトライしますか?って画面の時に座標を捨てずに置いておけばなんとかできるんじゃないかなぁ…とか思ったり。
3Dならわからないんですが、xyしかないのを見るに2Dゲームだと思うのですけれど…。

何かポインタ変数にすることで利点が生まれるのでしょうか?おしえてーかしこい人ー

アバター
みけCAT
記事: 6734
登録日時: 14年前

RE: ポインタはまだよくわかってないですが…

投稿記事 by みけCAT » 11年前

annojyou さんが書きました:void PLAYER::GetPosition(double *x,double *y){
*x=this->x;
*y=this->y;
//DrawFormatString(50,50,GetColor(255,255,255),"player差出座標(%f,%f)",this->x,this->y);
}

おそらくこの部分でポインタ変数を宣言した…ということなのかもしれませんが、これで行けたっけなぁ…とちょっと困惑気味だったり。
適当にコードを書いて試したところ、この書き方は別に問題ないと思います。

CODE:

#include 

struct AsumiKana {
	double x,y;
	AsumiKana();
	AsumiKana(double xx,double yy);
	void movexy(double dx,double dy);
	void getxy(double* x,double* y);
};

AsumiKana::AsumiKana() {
	x=y=0;
}

AsumiKana::AsumiKana(double xx,double yy) {
	x=xx;
	y=yy;
}

void AsumiKana::movexy(double dx,double dy) {
	x+=dx;
	y+=dy;
}

void AsumiKana::getxy(double* x,double* y) {
	*x=this->x;
	*y=this->y;
}

int main(void) {
	double bx,by;
	AsumiKana mizuhasu(100,200);
	mizuhasu.getxy(&bx,&by);
	printf("%f,%f\n",bx,by);
	mizuhasu.movexy(20,50);
	mizuhasu.getxy(&bx,&by);
	printf("%f,%f\n",bx,by);
	return 0;
}
実行結果

CODE:

100.000000,200.000000
120.000000,250.000000
http://ideone.com/DBmsMq

アバター
annojyou
記事: 0
登録日時: 11年前
住所: 大阪

Re: ポインタはまだよくわかってないですが…

投稿記事 by annojyou » 11年前

みけCATさん

書き方自体には問題はないんですね…勉強になります。
ふと思ったんですが、int型をdouble型に代入しなおしてやればさっきのプログラムは動くんじゃないかと思ったんですが…どうなんでしょう?
見たところint型をdouble型に置き換えてるのにdouble型にint型を代入する処理をして無いっぽいので、動かないのかなぁ…と。

int x,y;
double xx = x, yy = y;

とすれば動く…かも?しかし自信はないので書かない(`・ω・´)

アバター
annojyou
記事: 0
登録日時: 11年前
住所: 大阪

Re: ポインタはまだよくわかってないですが…

投稿記事 by annojyou » 11年前

CODE:

 
#include "pch.h"
#include "player.h"
#include "control.h"
 
PLAYER::PLAYER(){ 
     
    gh=LoadGraph("dat/画像/自機/001.png");
    psgh=LoadGraph("dat/画像/自機/ショット/0.png");
 
    memset(shot,0,sizeof(shot));
 
    speed=3.0; //スピード
 
    count=0;//カウント
 
    //初期位置
    x=180; 
    y=420; 
    //追加したdouble型
    double xx = x;
    double yy = y;

    //移動制御
    sayu=zyoge=0;
    naname=1.0;
 
    life=true;// 生きてるかどうか
 
    for(int i=0;ixx;
    *yy=this->yy;
    //DrawFormatString(50,50,GetColor(255,255,255),"player差出座標(%f,%f)",this->xx,this->yy);
}
 
一部分だけ書き換えてみたけど、こんな風にすれば動きそうな予感。
と、書いてたけどxyの型書いて無くね?と困惑中…何型なんだろう。
とりあえずせっかく書き換えたし投下。
► スポイラーを表示
最後に編集したユーザー annojyou on 2014年3月23日(日) 19:10 [ 編集 1 回目 ]

アバター
みけCAT
記事: 6734
登録日時: 14年前

Re: ポインタはまだよくわかってないですが…

投稿記事 by みけCAT » 11年前

annojyou さんが書きました:一部分だけ書き換えてみたけど、こんな風にすれば動きそうな予感。
これだけでは、どう見ても動かなそうな予感ですね。
なぜPLAYER::GetPosition関数の中でPLAYER::PLAYER関数のローカル変数の値が取得できると考えるのでしょうか…?
いや、仮に取得できるとしても、むしろx,yの値がxx,yyに反映されず常に初期値が返りそうですし…?

(◕‿‿◕)わけがわからないよ。

アバター
nullptr
記事: 239
登録日時: 13年前

Re: ポインタはまだよくわかってないですが…

投稿記事 by nullptr » 11年前

この日記を書いたかたは本当に全くポインタがわかっていないようですから、あまりいじめちゃダメですよみけさん。

質問の方は、GetPosition関数ではなくそれを呼び出す場所に問題があると思います。そもそも初期座標が返ってきておかしくない時に呼び出しているんじゃないですかね。そんな気がします。

アバター
annojyou
記事: 0
登録日時: 11年前
住所: 大阪

Re: ポインタはまだよくわかってないですが…

投稿記事 by annojyou » 11年前

いろいろわかってないですね…ポインタのお勉強をちょっとずつしていかないと。

さっき出したやつのローカル変数の値が取得…とかは全然わからないです…。でもとりあえず入門からやっていこうかと。

(しかし…ポインタって勉強してても実感がわかないなぁ…。)

Rittai_3D
記事: 525
登録日時: 12年前

Re: ポインタはまだよくわかってないですが…

投稿記事 by Rittai_3D » 11年前

ポインタは自分も理解できませんでした。というか、現在進行形で理解できていません。
自分はコードを書いて書いて書きまくり、そのコードの中で少しずつポインタを使って、そのうちに慣れてくるはず!作戦をとっています。
習うより慣れよ ってことです。
► スポイラーを表示

アバター
nullptr
記事: 239
登録日時: 13年前

Re: ポインタはまだよくわかってないですが…

投稿記事 by nullptr » 11年前

annojyouさんの場合、ポインタ以前にスコープについての知識が足りないかと思います。

CODE:

    //追加したdouble型
    double xx = x;
    double yy = y;
このように関数内部で変数を宣言した場合、それはローカル変数になります。thisポインタからアクセスすることはもちろんできませんし、この場合コンストラクタを抜ける時点でxxとyyは破棄されます。
スコープがわからないということは多くの基本的なローカル変数の寿命について正しく判断できない事を示します。そうなるとまだポインタを考えるのは早いと思います。ポインタとは変数のアドレスの事ですから、寿命についてわかっていない段階で触るべきではありません。

3D_3Dさんが書いていますが、質問先の内容の書き方はいくつか問題があります。本題から逸れるのでトピックの一貫性を保つために指摘はしませんでしたが。

CODE:

// C++ってこんな書き方だったっけ?しばらく使ってないから忘れてる…
double PLAYER::GetX() const
{
    return this->x;
}
まず、違いとしてはconst指定です。Getという名前なのに関数内部でDrawなどという関数を呼び出しているのは明らかに呼び出し側からは想像できない挙動です。3D_3Dさんのようにconst指定をすれば少なくとも何かの書き換えが起きないことを保証できます。
ポインタを引数に取る場合ですが、これはどちらかと言うとC言語的な書き方になります。C++ではこうは書かないです。ポインタを引数にしてしまうとconst性に支障も出ます。もちろんポインタを引数に取る場面はありますが、C++ではあまり良い例ではありません(C言語的書き方をしていくスタイルなら問題ないと思いますが)。

C++で書く方法は幾つもあります。幾つかあげときますね。

CODE:

// 3D_3Dさん的書き方。doubleの場合はコピーでもポインタと速度は変わらないですが、クラス宣言内部またはinline指定をすべきです。
inline double PLAYER::getX() const
{
    return this->x;
}

// 構造体にして返す コピーコストがあるがプリミティブ型のみなので問題ない
struct Position
{
    double x;
    double y;
};
Position PLAYER::getPosition() const
{
    return Position{ this->x, this->y };
}

// tuple
std::tuple PLAYER::getPosition() const
{
    return std::make_tuple( this->x, this->y );
}

// 仮にサイズの大きい変数を返す場合、const参照させる方が効率的ではある(ただしPLAYER変数が生きている間しか参照は有効でない)
const BigVar& PLAYER::getBigVar() const
{
    return this->bigVar;
}
ポインタがわからないと参照はわからないと思いますが…。掲示板はあまり見ませんが日記は見てるので、ポインタについてわからないところがあったら日記にしてみれば私や私より熟練の方が返事をくれると思います。もちろん掲示板でもいいですよ。

アバター
usao
記事: 1889
登録日時: 12年前

Re: ポインタはまだよくわかってないですが…

投稿記事 by usao » 11年前

ポインタがピンと来ないなら,とりあえず
「ポインタなんか無くても書けるよ派」になってみるとか.
(脳内シミュレーション的な意味で.本当になってしまってはダメですよ!)

自分でも60%くらい何言ってるかわからない感じですが,
ある機能を使わないというのは一種の「縛り」状態だと思うので もしかすると
そうすることで逆にその機能のありがたみとか意味とかがわかったりして…みたいな?

例えば,「おまえは自分で関数を作ることを禁ずる」と言われたら
そんな苦行命令を下した者を呪うと同時に,「くそっ,こんなとき関数があれば…!」と2分に一回くらいの頻度で思うでしょう.
ポインタでも同じように「ポインタさえあれば…!」とか思った時点でポインタのことがわかってるというかそういう謎の仕組み.

ISLe
記事: 2650
登録日時: 14年前

Re: ポインタはまだよくわかってないですが…

投稿記事 by ISLe » 11年前

関数を作ると、任意に関数を呼び出して使うことができますよね。
ポインタを使うと、任意の変数を処理対象にすることができます。
関数はコンパイル時に存在しないとコンパイルエラーになりますが、ポインタはコンパイル時には存在しない変数も使えます。
だから実行するたびに変化するものに強いのです。

余談ですが、スコープとライフサイクルは混同しないように注意しましょう。