• ベストアンサー

ポインタのポインタ

ポインタのポインタは何に使うか知ってるか? と言われ答えられませんでした。 メモリ上の xという変数の住所を yという変数に入れ、yの住所を zに入れる。 要するに、 ATMの4ケタの暗証番号を書いた紙xがあって、 そのありかをyという紙に書いて、 そのありかをzという紙に書いたということでしょうか? でもzを読めばyにたどり着き、yを読めばxにたどり着くわけですから、 暗証番号を隠したことにちっともならないと思うのです。 いったい、何に使うのでしょうか?

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

  • ベストアンサー
  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.7

【宝探しゲーム】 C地点にある宝を探しに、A地点を出発する。 A地点で渡された地図には、途中のB地点までのルートが書いてある。 AはBを指している、と読める。Aは、Bへのポインター。 B地点で渡された地図には、ゴールのC地点までのルートが書いてある。 BはCを指している、と読める。Bは、Cへのポインター。 すなわち、Aは、Bを経由してCを指している、と読める。Aは、Cへのポインター(つまりB)へのポインター。

その他の回答 (7)

  • gooshibu
  • ベストアンサー率50% (2/4)
回答No.8

こういう例えはいかがでしょうか? 名刺入れに名刺が100枚入っています。 この名刺を見る時に、あるときは個人名順で、あるときは会社名順で見たいとします。 その為には個人名順、会社名順に並び替える必要がありますが、それはなかなか大変な作業です。 そこで、名刺に今の並び順で1から100まで番号をつけ、紙を2枚用意してそこに名前順に並べた番号と会社順に並べた番号を書いておきます。 次のような感じです。 名刺の順番  1番 B社 おおお氏  2番 A社 あああ氏  3番 C社 えええ氏  4番 E社 ううう氏  5番 D社 いいい氏 名前順の紙→ 2 1 3 5 4 会社順の紙→ 2 5 4 3 1 名前順に見たい場合は名前順の紙に書かれた番号にしたがって名刺を見ていき、会社順の時は会社順の紙の番号にしたがって名刺を見ていくことになります。 現実の名刺と紙ではうまく機能しませんが、コンピュータ上では番号から名刺そのものをすぐに取り出すことができるので有効なやり方といえます。 この時、番号がアドレスなので、この番号を書く場所はポインタ、それが複数並んでいるので紙はポインタ配列となります。ポインタ配列の先頭アドレスを示すものはポインタへのポインタとなります。 名刺を順番に見るという処理をひとつ用意し、入り口に紙用の受け皿であるポインタポインタを置きます。 紙の受け皿には名前順の紙か会社順の紙(どちらもポインタ配列)を渡すと、希望する順番で名刺を見るという処理を作ることができます。 すでに回答にありますが、ポインタのポインタは、ポインタのアドレスを入れるための物です。 当然ポインタポインタのアドレスを入れる必要があれば、ポインタポインタポインタ(***ppp)が必要になります。そこに何を入れるかによって必要な器の名前がつくだけで、これがどこまで続くのかなどというのはあまり考えない方が良いですよ。

  • OKbokuzyo
  • ベストアンサー率43% (130/296)
回答No.6

No3です。 >ポインタのポインタのポインタ >にするともっと良くなるのでしょうか? >それとも良さは2回のポインタでストップするのでしょうか? >それとも2回よりも3回のほうが良さが上がるのでしょうか? >3回よりも4回のほうがよさが上がるのでしょうか? >もちろん、「良さ」の「上がり方」はだんだん減っていくとは思います。 >対数関数的とでもいいましょうか。 >それとも良さは2回までで3回目以降はx軸に水平なのでしょうか? そういう意味で言えば基本的には2回までです。 また場合によってはポインタを使った方が 不利となる場合(※ 現実にはほとんどありえませんが)があります。 もう少し定量的に考えましょう。 ポインタはそれほど特別なものではありません。 変数はデータを格納するものであるのに対し、 ポインタはアドレスを格納するための変数ということができます。 変数には格納できるサイズがあることはご存知かと思います。 intのサイズはそのシステムの1ワード、すなわち32bit環境ならば4バイトです。 そのほかにも文字の格納に使うcharは1バイト、 doubleは有効桁数10桁の数値を扱うことができるように8バイトです。 そして、ポインタはアドレスを格納する変数ですから アドレスを格納するために必要なサイズであればいいわけです。 具体的には、アドレスを格納するためのサイズはintと同じで intが4バイトのシステムならポインタ変数のサイズも4バイトとなります。 次の場合を考えて見ましょう。 char c[4]; char *pc[4]; char型の配列のサイズは1×4で4バイトです。 これに対し、ポインタ配列のサイズは4×4で16バイトです。 すなわちメモリの消費量で言えばchar型の配列のほうが優秀です。 double d[4]; double *pd[4]; double型の配列のサイズは8×4で32バイトです。 ポインタ配列は先ほどと同じで4×4の16バイトとなります。 この場合はポインタ配列のほうがメモリの消費量は少ないということになります。 そしてさらに、このポインタ配列もポインタで扱えば たった4バイトで32バイトのデータを扱うことができます。 現代では実際に扱うデータはこのようにcharやdoubleだけということはなく、 もっと複雑で混ざりあっていますから、 ポインタでデータの在り処を示すというのはメモリの有効利用という点で非常に有利なわけです。

  • YOKO-bee
  • ベストアンサー率50% (2/4)
回答No.5

何に使うか・・・難しい質問ですよね。 使い道について、「文字列の配列の受渡し」に使うという表現が 個人的にしっくりきます。 一例ですが、*week[]={"月曜","火曜","水曜","木曜","金曜",NULL};と ポインタ配列を作成して、表示関数へポインタのポインタで渡します。 この時、作成者が同じかインターフェイス設計が確定していれば、 固定長の2次元配列で渡せるかもしれませんが、エディタなどを 作成する場合は固定長という訳にはいきません。(たぶん(-_-;)) 一例を元にサクッと書いたソースです。 (全角スペースは置換してください。) /*--------------------------------------------- #include <stdio.h> void dspout(char **); int main() {  char *week[] = {"Sunday","Monday","Tuesday","Wednesday",           "Thursday","Friday","Saturday",NULL};  dspout(week);  getchar();  return 0; } void dspout(char **pweek) {  for(;*pweek!=NULL;pweek++)  {   printf("%s\n",*pweek);  } } ------------------------------------------*/ このプログラムを実行してアドレスの動きを見ていくと、なんとなく 「文字列の配列」の受渡しに使うと効果があるって事がわかるんじゃ ないか~と思います。(ちょっと投げやりで、すいません) karasu4649さんの例えだと、確かに「ポインタ」でいいじゃないか? とも思うんですけど、文字列の配列を全部表示・処理する場合に有効 ということで、私は考えております。 かなり私見ですが、お役に立てれば幸いです。<(_ _)>

回答No.4

「参照」や「ポインタ」は「リファレンス」と呼ばれ 一般にそれがconstで無い場合には、はリファレンス先の変更を 目的とします。intのリファレンスはint=数値の変更を目的と するのです。従ってお尋ねの「ポインタのポインタ」は ポインタのリファレンスですので、一次の変更対象は ポインタ=アドレスとなります。もちろんその先も変更できます。 つまり、 > ポインタのポインタは何に使うか知ってるか? については、「整数は何のために使うのか?」と 同類の質問で「何にでも使えるので特定の目的は無い」が正解です。 より踏み込んで具体的に予測すると 「たぶんアドレスの変更が目的でしょう」 程度には答えても良いかもしれません。

karasu4649
質問者

お礼

while文はすべてfor文で書き直すことが出来ますので、 while文は「いらない」と言い切ることが可能です。 それでは、ダブルポインタはいらないと言い切ることは可能なのでしょうか? 「いらないけどあると便利」 なのか 「ダブルポインタでないと実現できないことがある」 なのか、どっちなのでしょうか?

  • OKbokuzyo
  • ベストアンサー率43% (130/296)
回答No.3

まずポインタを利用する利点を抑えておく必要があると思います。 データを隠すためにポインタを使うわけではありませんから。 ポインタを使う理由は主に次の2点です。 1.ポインタの指し示す先が配列でも変数でも同じように扱えること。 2.ポインタの指し示す変数や配列がメモリ上のどこにあっても気にする必要がないこと。 1点目に関しては特に説明不要かと思います。 2点目についてですが、 読み込まれたデータはメモリ上のどこかに適当に格納されます。 具体的に言えば、次のように宣言すると int a = 100, b = 200, c = 250, d = 300; a, b, c, dはそれぞれメモリ上のどこかに格納されます。 この4つのデータに対し、例えばそれぞれ2倍にするというように 何かデータ加工を行いたい場合を考えます。 2倍にするだけならa = a * 2というようにすれば良いだけですが すべてにこのようにアクセスしていては非効率です。 今はデータがたった4つですが、これが100個、1000個となると大変でしょう。 また、データの数は頻繁に減ったり増えたりするかもしれません。 なのでこれらデータを配列に格納して、効率を良くしてやる必要があります。 このとき、このデータを普通の配列に格納するのではなく、 ポインタ配列へ格納します。 int *pt[4]; pt[0] = &a; pt[1] = &b; pt[2] = &c; pt[3] = &d; このようにすればデータがどこにあるのか気にする必要がなくなります。 今回、データはint型ですが、実際には構造体だったり複雑な形を取ることが多いので ポインタ配列にしておくとメモリの有効利用ができ、効率が良いわけです。 あとは、No1さんがおっしゃっている通りなのですが さきほど言った「2倍にする」というようなデータ加工処理部分を別関数とすることを考えた場合 このポインタ配列のポインタを渡すようにすれば さらにメモリの有効利用をすることができるということです。 Cやポインタに限らず話をすれば メソッドに渡す引数は基本データ型以外(すなわちオブジェクト)は参照渡となります。 メソッドからメソッドを呼び出すというように 何度もメソッドを呼び出すことを考えた場合、 このときの引数はアドレスで引き渡されているために 呼び出し元がどこなのか意識することなく同じデータを扱うことができるわけです。 そういう意味ではこれもポインタのポインタとつながる話でしょう。

karasu4649
質問者

お礼

ポインタのポインタにすると効率が良くなるとのことですが、 そうしますと、3回のポインタ、つまり ポインタのポインタのポインタ にするともっと良くなるのでしょうか? それとも良さは2回のポインタでストップするのでしょうか? それとも2回よりも3回のほうが良さが上がるのでしょうか? 3回よりも4回のほうがよさが上がるのでしょうか? もちろん、「良さ」の「上がり方」はだんだん減っていくとは思います。 対数関数的とでもいいましょうか。 それとも良さは2回までで3回目以降はx軸に水平なのでしょうか?

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

リストや二分探索木を操作するときに値を検索しなければならない場合に, ポインタのポインタを使うと後の操作が簡単になることがあります.

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.1

コンソール・アプリケーションに実行時の引数を渡すとき、 main関数を int main(int argc, char **argv) { /* 何かの処理 */ } のように書きます(別の書き方もあります)。 第2引数argvは、char型へのポインタへのポインタです。 各々の引数の文字列にアクセスする際は、 argv[0], argv[1], argv[2], ...や *argv, *(argv+1), *(argv+2), ...のように書きます。 暗証番号のたとえは今一つふさわしくないと思います。 隠す隠さないの話ではありませんので。

karasu4649
質問者

お礼

暗証番号のたとえは捨てます。 それでは自動販売機などはどうでしょうか? 自動販売機という関数にお金という引数をぶち込むと ジュースという戻り値が帰ってきます。 ここで、お金をコピー機で印刷してから関数に入れると、 これは値渡しですので、自分のお金は一切減りません。 関数の内部でいくらさっぴこうが、自分の財布は痛くも痒くもないということになります。 普段、私たちは自動販売機では参照渡しでジュースを買います。 ですから、関数に渡したお金が引き算されると自分の財産が減るのです。 それでは、これをダブルポインタでジュースを買うと どういうことになるのでしょうか? この例えもおかしいようでしたら、何か例えを作っていただけると ありがたいです。 僕は頭が悪いので例えが無いとあんまり理解ができないです。 よろしくお願いいたします。

関連するQ&A