ポインタに関連するトラブルの原因と解決方法

このQ&Aのポイント
  • ポインタに関連するトラブルの原因と解決方法を解説します。
  • 特定のポインタが異なる結果を返す問題についての対処方法を紹介します。
  • ポインタのアドレスが同じでありながら異なる結果が返される理由について説明します。
回答を見る
  • ベストアンサー

ポインタに関するトラブル

pointという座標を表す変数x,y,zつ保持するクラス型があったとして point *a = point型のポインタを返す関数(); という式を作ったんですが、なぜか、 右辺と左辺はどちらのポインタも指すアドレスは確実に同じなのに。 値を参照しようとすると違う結果が出ます。具体的には 右辺から参照した結果が 50(正しい結果) (*a).x を表示した結果 左辺から参照した結果が -9.25596e+061(?) (*point型のポインタを返す関数()).x を表示した結果 という結果で、完全に同じアドレスを保持するポインタなのに 実行した結果が違って混乱しています。まったく原因がわかりません 説明不足で申し訳ありませんが、なにが問題か分かる方がいらっしゃったらお願いしますm(_ _)m

質問者が選んだベストアンサー

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.4

> 自動変数のアドレスをもらって、直ぐにコピーしない 違います。 (*a).c[0] も「たまたま」値が上書きされなかっただけです。 アドレスが自動変数が使用する領域を指していること、そのアドレスにあったクラスは既に無効になっていること、には違いはありません。 現行のプロトタイプを使うなら、関数を抜けても消えないもの(グローバル変数や、newで確保した領域など)を返す必要があります。 どちらも、別の点で扱いに注意が必要です。 あるいは、呼び出し側をポインタではなく point a; と実体を用意して ・アドレス渡しや参照渡しを使う void 関数(point * ret,point 原点,double w,double d); void 関数(point & ret, point 原点,double w,double d); → point a ;  関数(&a, 原点,100.,100.); // point * ret,~  関数(a, 原点,100.,100.); // point &ret,~ ・実体を返す関数にする point 関数(point 原点,double w,double d); → point a = 関数(原点,100.,100.); ※ pointクラスが実際にはもっと複雑なら、コピーコンストラクタや =のオーバーライドが必要かも。 ・pointクラスのメッソドとして定義する class point { point & method(point 原点,double w,double d){ ~ return *this; //a.method(原点,100,100).c[0] みたいな使い方をしたいなら、自分自身の参照を返すようにする) } → point a ;  a.method(原点,100,100) ;

その他の回答 (5)

  • wormhole
  • ベストアンサー率28% (1621/5656)
回答No.6

>自動変数のアドレスをもらって、直ぐにコピーしないと、 自動変数のアドレスを戻り値とすること自体が間違いです。

noname#164673
noname#164673
回答No.5

point型のポインタを返す関数()が返した結果を参照する時点で、実体が無くなっているとその様になる事があります。 point型のポインタを返す関数(){ point ans(0,0,0); return &ans; } ↑この様に関数を記述すると、関数の実行されている時点では、ansの値は正常ですが、リターンした後、スタックが上書きされるとansの値も上書きされます。 point型のポインタを返す関数(){ static point ans(0,0,0); return &ans; } とすれば、値は静的領域に残るので、いつまでもansは有効です。 とりあえず、思いついたので、参考にして下さい。

回答No.3

point* 関数(point 原点,double w,double d){ point p = {0,0,0}; // 自動変数の point* a = &p; // アドレスを return a; // 返してますよ! }

nasumiso2022
質問者

補足

なるほど・・・自動変数ってそういう意味なんですか・・・ いろいろ考えて分かりました。自動変数のアドレスをもらって、直ぐにコピーしないと、もともとそこにあったアドレスの指す変数は、スコープをでてしまっているから、上書きされちゃってたんですね・・・

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「自動変数のアドレスを返す」というボケをかましているとか?

nasumiso2022
質問者

補足

それはどういう意味なのでしょうか・・・ 説明不足だったので、補足にソースコードを付け足させて頂いたので、それを見てなにか分かることがあればよろしくお願いします。

  • wormhole
  • ベストアンサー率28% (1621/5656)
回答No.1

具体的にどういうコードを書かれているのか書いた方がよいかと思います。 とりあえず現状いえることは書かれているコードのどこかがおかしい(あなたが思った動きをするコードにはなってない) くらいです。

nasumiso2022
質問者

補足

説明不足ですみません。 問題が再現されるギリギリまでソースコードを削ったものがこれです ////////////////////////////////////////////////////////// #include <iostream> #include <string> #include <stdio.h> using namespace std; class point{ public: double c[3]; }; point* 関数(point 原点,double w,double d){ point p = {0,0,0}; point* a = &p; return a; } int main(void){ point 原点; 原点.c[0] = 0; 原点.c[1] = 0; 原点.c[2] = 0; //////////////////////////////////////////////////////////// //左辺と右辺は同じはずなのに、表示すると違う結果に point *a = 関数(原点,100,100); //////////////////////////////////////////////////////////// printf("■アドレスの比較 \n"); printf("%p \n",a); printf("%p \n",関数(原点,100,100)); printf("■値の比較 \n"); printf("%f \n",(*a).c[0]); printf("%f \n",(*関数(原点,100,100)).c[0]); getchar(); return 0; } ///////////////////////////////////////////////////////////// これを実行すると、アドレスは同じなのに、値が違うという結果になります。

関連するQ&A

  • フレームポインタについて

    こんにちは x86の場合、フレームポインタは関数呼び出し直後のスタックポインタの値を保持してると書いてありました スタックは引数、リターンアドレス、ebp保存値、ローカル変数の順番で格納されると認識しています 関数呼び出し直後のスタックポインタの値とは、正確にはどこを指してるのでしょうか よろしくお願いします

  • 多次元配列のポインタ渡し

    C++を使用しています。 多次元配列を関数の引数として渡したいとき、関数側では void A::Func(int a[10][20][30])~ 呼びだし側では Finc(a); とやればいいのはわかります。 お聞きしたいのは、仮引数として呼び出された配列(上でいうa)をクラスのメンバ変数として保持したい場合の方法です。 aは先頭アドレスなのでそこを差すポインタを受ければいい、っていうことはわかりますが、 この方法ですと、受けたメンバ変数が配列みたいに[]を使ってアクセスできません。 (メンバ変数のポインタは配列じゃないから当然ですよね) これを通常の配列みたいに扱えるようにするにはどうしたらいいでしょうか。

  • f(x)=f1(x)におけるf(x)は何関数?

    例えば、xを変数にもつ以下の3つの関数、f(x)=f1(x)、f(x)=f2(x)、f(x)=g1(x)がある場合、この左辺のf(x)は何関数と呼ぶのでしょうか? 左辺の部分は、「xを変数にもつ関数」ということで、より広い一般的な関数を表し、 右辺は、「その実際の中身を表す関数」だと思うですが、 左辺のf(x)のような関数を何関数と呼ぶのでしょうか? (基本関数とか広義関数とかでしょうか(すみませんかなり適当にあてずっぽうに書いています。)) どなたか正しい呼び方を教えてください。 よろしくお願いします。

  • ポインタに含まれる情報は [C言語]

    ポインタに含まれる情報は代入した変数のアドレスですが、アドレス元の変数の大きさは含まれないのでしょうか?ポインタの中の情報を見てみても、参照できる変数が使用しているメモリの先頭アドレスしか入っていません。変数の大きさはどうやって知るのでしょか?回答よろしくお願いします。

  • ポインタを引数で使用する場合

    初心者です。 ローカル関数でポインタを引数で使用する場合の定義で int A (int *x,int *y) とする場合の*はポインタの宣言としての*なのでしょうか? これまでの例題ではメイン関数のなかでポインタを宣言しアドレスを代入し・・・という使い方だったのですがローカル関数で引数を使用するさいはメイン関数内ではポインタの宣言はないので関数の定義と同時にint *x とint *yを宣言するという事なのでしょうか? それ以降の*は間接参照演算子ですね。

  • ポインタ引数をさらにポインタ引数に渡す方法

    ポインタ引数をさらに関数のポインタ引数として設定するには、 どうしたらよいのでしょうか? イメージとしては、 int 関数A(*a *b) { *a = 5; *b =3; 関数B(*a *b) } またポインタ引数の関数内で、 ポインタ指定せずに変数を使えるのでしょうか? int 関数A(*a *b) { a = 5; b =3; 関数B(*a *b) }

  • ポインタの宣言

    ポインタを宣言するとメモリ上に、ポインタ変数を格納するための領域が確保されます。ポインタ=アドレスというのは大丈夫なのですが、 int *b のようにどうして、ポインタに型があるのでしょうか?単に変数のアドレスを表示するだけならば型はいらないと思うのですが。 またこのとき宣言された変数は *b ではなくて b であってますよね?

  • DXライブラリ:ポインタと配列?

    初心者です。よろしくお願いします。 C言語とDXライブラリを利用してゲームを作成中です。 GetMousePointの関数を利用して、マウスの座標がその時、どこにあったのか。という情報を配列に格納したい、と考えています。 リファレンスページを参照すると、 int GetMousePoint( int *XBuf, int *YBuf ); このように書かれているのですが、配列に格納しようとするとフリーズしてしまいます。 【1】 GetMousePoint(&x,&y); zahyou[i] = x; 最初上のようにしてフリーズしたため、ああ、アドレスを格納してしまったのか。と思いまして、 下のように直しました。 【2】 GetMousePoint(&x,&y); int *a = &x; zahyou[i] = *a; が、またフリーズが発生しました。ポインタを説明しているページを見てはいるのですが、ポインタの指すアドレスの中にある数値の取り出し方がイマイチ掴めません。 なぜか別の場所で処理している、 【3】 (x = x-230)/=40; x = x*40+250; このような処理に関しては動くのですが・・・。これはアドレスを直接に利用している、ポインタの中身を利用しているのではない、ような気がするのですが、なぜか動いています。 (上の処理より下の箇所で利用しています) 【1】【2】【3】のそれぞれがどう言った処理を行っていて、こうすれば良い。等のアドバイスをいただけないでしょうか。 あつかましいとは思いますが、よろしくお願いします。

  • ポインタ演算

    http://wisdom.sakura.ne.jp/ このサイトの講座から引用 *po++; とやると、多くの人の期待に反した結果が得られると思われます このときは、アドレスが指す変数ではなくポインタの値がインクリメントされてアドレスを参照されます とありますが、実際に実行してみると、インクリメントされた後に参照 されます。なぜでしょうか、ご存知の方は回答お願いします。 OSはWindows コンパイラはBorland C++ Compilerです。

  • ポインタ変数とポインタのポインタ

    ポインタ変数の宣言 char *a[]; をしたとき僕の中では a[0],a[1]...という、ある文字列A,B,C...の最初のアドレスを指すポインタが、配列になっているものを宣言していると理解していました。 しかしこの次に、ポインタのポインタが出てきました。僕はこれを、 ある変数を指し示すアドレスのアドレスである、と理解しました。 この2つは1つめはいくつかのアドレスを指し示すもの、2つ目は1つのアドレスを指し示すものであるとして、僕の中で異なったものであると理解していましたが、参考書「C標準コースウェア」によると プログラムにおいて、関数でポインタ配列を受け取るときchar *p[]はchar **pとしてもよい と書かれており、またその実例として、 (9-5) #include <stdio.h> void disp (char *p[],int n){ int i; for (i= 1;i<n;i++){ printf("%s\n",p[i]); } } int main(void){ char *girl[] = {"Arica","Candy","Lisa"}; disp (girl,sizeof(girl)/sizeof(girl[0])); return 0; } というプログラムが書かれていました。 ここで一気に訳が分からなくなりました。 char *girl[] = {"Arica","Candy","Lisa"}; と宣言されているため、 girl[0]はAricaという文字列の最初のアドレスを指すポインタ、 *girl[0]はAricaという文字列を直接指し示していると解釈しています。 girlは{"Arica","Candy","Lisa"}という文字列の配列の最初のアドレスを指し示していると考えました。 sizeof(girl)を使った時に不思議なのですが、 girlはどのように配列の終わりを理解しているのでしょうか? (配列の要素数を渡していない点が不思議です。) また、 disp側が受け取ったのは*girl[]であり、いくつかのポインタの配列ですが、渡したものはgirlという要素数がないポインタ1つだけです。 そして最初の疑問が出てくるわけですが、*p[]を**pと書きかえてみると、 文字列のアドレスを示すgirlという名の1つのポインタを渡すと、pという名のポインタのポインタで受け取るというのも、よくわからなくなっています。 おそらくポインタ配列に対する理解がどこかでずれているようですが、自分でどこがわからないのかわからなくなっています。 どうかご教授ください。

専門家に質問してみよう