トップページ⇒tech
569コメント176KB

ポインタの説明をしてみて初めて解かる難しさ

■ このスレッドは過去ログ倉庫に格納されています
0001プロだよNGNG
お前らポインタという物を初心者にも
解かるように説明しやがりください。

これが意外と苦労するんだなw
0232デフォルトの名無しさんNGNG
>>231
つかっとるやないか・・・
0233前スレ755NGNG
イやもっと積極的にさ。アセンブラなんかだと、アクセステーブル入れ替えとかのテクで使うことはあったんだけど、c++ではほとんど使わなかったのよ。
0234デフォルトの名無しさんNGNG
>>231
ダブルぐらいならmain()の引数として毎度おめにかかってるだろ

配列的使い方以外でありがちなのは
関数で「ポインタを(戻り値ではなく)引数経由で返す」場合かな
これだけで一段間接参照が増えるから少なくともダブルにはなる
0235デフォルトの名無しさんNGNG
あ、C++なら確かに参照だの使えるから機会は減るかもなあ
0236231NGNG
あ、ポインタの参照わたしは使ってたね
イやもっと、こちらの予想だにしないトリッキーなコードを期待しているんだけれど
0237デフォルトの名無しさんNGNG
トリッキーなコードを求めるでない。
0238デフォルトの名無しさんNGNG
普通が一番じゃよ
0239デフォルトの名無しさんNGNG
ポインタとは、君の人差し指で何かを指したときの機能を分解すればわからないかな〜。

たとえばこういう話。
自分は指を相手の頭にさす。
そして言う。
「俺はそれをさした。」
ここで、それについて考えてみる。
それは、頭であり、番地であったり、場所であったりする。

こんなのどうでしょ。
0240デフォルトの名無しさんNGNG
3行目ぐらいでわけわかんなくなった
0241デフォルトの名無しさん NGNG
これで初心者の人も理解できましたよね?
0242デフォルトの名無しさんNGNG
つまりポインタは指ですね。
0243デフォルトの名無しさんNGNG
int* hoge;
hoge = &foo;

*hoge → foo(保持している値)
hoge → foo(アドレス)
&hoge → (気にするな)

ポインタって、こんな感じでいいの?
0244デフォルトの名無しさんNGNG
気にしなくてもいいけどさぁ、hoge(アドレス)にしとけば?
かしこくみえるよ。
0245デフォルトの名無しさんNGNG
>>243
fooは左辺にかくとfooのアドレス(LVALUEをこう書いちゃうのは単純化かもしれんが)
右辺に(式の中に)かくとfooの値

hogeも左辺にかくとhogeのアドレス
右辺に書くとhogeの値=fooのアドレス

*hogeは左辺にかくとhogeの保持してる値=fooのアドレス
右辺に書くとfooの値

&hogeは式だからかならず右辺値で
hogeのアドレス
0246デフォルトの名無しさんNGNG
という訳でポインタが分からない奴は
変数とか式とか
もっと基本的なことから勉強しなおそう
0247デフォルトの名無しさんNGNG
これでいい?

// GCC version 3.2 にて動作確認
#include <stdio.h>
int main(void) {
int* hoge;
int foo = 1;
int* bar;

hoge = &foo;
printf("%d\n", *hoge); // fooの値が表示される。

*hoge = 2;
printf("%d\n", foo); // fooの値が変わるぞい

bar = hoge;
*bar = 3;
printf("%d\n", foo); // fooの値が変わる

return 0;
}
0248デフォルトの名無しさんNGNG
>>247
せっかくgccもってるなら、cc -Sで出るasmのコードを見たほうが
あからさまにてっとり速い気がするけど
0249デフォルトの名無しさんNGNG
ごめん、アセンブラ読めないの

私の環境はMinGWなのね。
cc ないの
0250デフォルトの名無しさんNGNG
>>239 みたいな本質から外れたアホみたいなたとえ話する困った馬鹿がよくいるよなw
0251デフォルトの名無しさんNGNG
だれか、>>247 にポインタを教えてやれよ。
0252デフォルトの名無しさんNGNG
○○市長が住民票の写しを発行するのである。
×月□日の時点では、○田 △夫が○○市長なのである。
だから×月□日発行の住民票の写しは、○田 △夫が発行するのである。
'○○市長' てのが変数名だとすれば、こいつはポインタの役割をする変数なのである。

※私を煽る人は、煽ってることが分かりやすいように、
 文末に「ゲロッピーピュフプー」と書いて下さい
0253デフォルトの名無しさんNGNG
ゲロッピーピュフプー
0254デフォルトの名無しさんNGNG
(笑点風に)
「紙をくれ」って言ってる人に
1枚とって渡してあげるのが「値渡し」
「紙なら隣りの用具庫にあるよ」って言って出て行くのが「ポインタ渡し」
0255デフォルトの名無しさんNGNG
そうすると、課長の役割はなんですか?

ゲロッピーピュフプー
0256デフォルトの名無しさんNGNG
「理解してもらわなくてもいいから、どんな感じかを伝えたい」ならともかく
解らせるつもりなら、他の何かに喩えたって無駄。
0257デフォルトの名無しさんNGNG
理解するのは個々人の努力
強制的に理解させようなんて思っても無駄
0258デフォルトの名無しさんNGNG
>>254
「参照渡し」じゃないのか?
0259デフォルトの名無しさんNGNG
宝物が値
宝地図がポインタ
宝地図の地図がポインタのポインタ
0260デフォルトの名無しさんNGNG
変な説明いらんよ
ポインタはポインタだ
0261デフォルトの名無しさんNGNG
>>258
参照はこうじゃないか?
相手「紙なら隣りの用具庫にあるよ」
自分「そうか。ならXX(部下)、紙取ってきてくれ」
0262デフォルトの名無しさんNGNG
地図とか指はさぁ、増やしたり減らしたりできんじゃん。
0263デフォルトの名無しさんNGNG
つまり参照の説明にはなってるけど、ポインタの説明にはなってないってことだな。
0264258NGNG
>>261
参照渡し:4020件
ポインタ渡し:553件
ちなみにそれはエージェント指向(?)
0265デフォルトの名無しさんNGNG
>>262
基本的な概念は同じ。
アドレスを指すという意味ではもう少し別の例えが必要だけど、
全く知らない初心者に教えるなら地図でも十分かと。
0266俺は文系だがNGNG
でもやはし、アセンブラの足し算見たいの理解させればポインタ理解するんでない?
それで分からないと...
0267デフォルトの名無しさんNGNG
参照を理解させれば十分だ、という考えが、参照さえできればアドレス演算ができるポインタは不要ということにつながるわけだな。
0268デフォルトの名無しさんNGNG
だからさぁ、全く知らない初心者に説明しようというときに
「地図」だの「指」だの「頭」だの、いきなりコンピュータと無関係な
たとえ話するからダメなんだよ。
http://mikata.curiocube.com/hello/ch03_memory1.html
こんな感じでいいだろ?
0269デフォルトの名無しさんNGNG
              ∩
             | |
             | |
             | |
             | |
       ∧_∧  | |    / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
      ( ´Д`)//  < いいでぇーす。
      /     /    \_____________
     / /|    /
  __| | .|    | __
  \   ̄ ̄ ̄ ̄ ̄   \
  ||\            \
  ||\|| ̄ ̄ ̄ ̄ ̄ ̄ ̄|| ̄
  ||  || ̄ ̄ ̄ ̄ ̄ ̄ ̄||
     .||              ||
0270デフォルトの名無しさんNGNG
問2:
 ポインタを使うことでスマートに実装できるという簡易な実例を列挙せよ。

/* こういうときポインタ使うよね、って例をだせということですわ */
0271デフォルトの名無しさんNGNG
>270
・swap
・List
・コールバック関数
0272デフォルトの名無しさんNGNG
>>270
dump
0273デフォルトの名無しさんNGNG
>>270
仮想関数
0274デフォルトの名無しさんNGNG
読み始めたばかりだが、「ポインタそのものに格納できる値は4byte」とか言っている>
>12にまだだれも突っ込みを入れていない?

といいつつも、漏れのポインタの認識もこんなだが。

[ポインタとは]
ポインタとは*演算子を使うことで特定のオブジェクトを間接参照することが出来る変数である。

まず、ポインタは以下の手順を用いて間接参照したいオブジェクトを指す手順が必要である。

手順1. 間接参照したいオブジェクトの型に *をつけて宣言する。
手順2. 間接参照したいオブジェクトのアドレスを代入する。

以上の手順を踏むと、ポインタ変数に*演算子を使って2で指定したポインタ変数を
間接参照できるようになる。

また、ポインタの値を変化させることによって間接参照するオブジェクトを
変えることができる。例えば、ポインタの値に++とすると一つ後ろのオブジェクト、
--とすると一つ前のオブジェクトというように。これはポインタ演算と呼ばれている。

ところがこのポインタ演算はメモリ破壊等の原因となりやすい。
例えば、++しすぎてあてずっぽのところを指してしまったりとか。
このためJava言語はポインタ演算のようなことが出来ない仕組みになっている。
0275デフォルトの名無しさんNGNG
考えてみたらポインタ演算なんか使ったことないな
通信などでメモリ直接いじるとき除く
0276デフォルトの名無しさんNGNG
そ、そうか?
多くのポインタ演算は配列演算子で書き換えることも出来るけど
結局Cでは内部的にはポインタ演算なので(危険度まで含めて)一緒でしょ
それに

c = *p++; // fetch and incr
*dst++ = *src++;// copy

みたいなのが簡潔に書けるのはやはり便利だけど
ほんとにつかわないの?
0277デフォルトの名無しさんNGNG
C++ばかしでポインタはnewしたオブジェクトにしか使わないしそれもvectorとかに突っ込んでるし...やっぱつかわね
0278デフォルトの名無しさんNGNG
>276
そういうのは、配列の書き方でした方が分かりやすいしなぁ。
(デバック時も含めて)

線形リストみたいなのだと、本質的にポインタを使うわけだが
線形リストに使うポインタでは、ポインタ演算を使う意味ないし。

この大きく分けて2つの使い方があるってのが、
ポインタの複雑さなんだろうな。
0279デフォルトの名無しさんNGNG
>>270
配列の途中から途中までを関数に渡して処理させる場合。例えば

int a[10];
sort(&a[5], 5);

とか。
0280デフォルトの名無しさんNGNG
>>279
な、なんかキワどいコードだね・・・。
まぁ、簡潔に見せるために、省略してるんだろうけど。
0281デフォルトの名無しさんNGNG
結局、ポインタは goto とかと同じで、
あれば便利、なくても問題ないなら別にいい
ってレベルの様な気がする
0282デフォルトの名無しさんNGNG
>>281
昔のC言語の教科書のレベルでも、
文字列操作とか、FILE* とか、ポインタは使うのですが。
0283デフォルトの名無しさんNGNG
要は
ポインタは難しいね、
って言われるようなポインタの利用法は
使い道自体が難しいってことかもな。
直感的にわかりづらくなるのは間違いないし。
0284デフォルトの名無しさんNGNG
でも少なくともポインタわからないて言う人にはプログラム書いてほしくない
0285281NGNG
>>282
でもポインタ使っていることを意識させない言語もあるでしょ
仮に言語レベルで隠すことが出来ればそっちのほうが初心には分かり易いんじゃないかって話

>>284 の言うとおり、分かっていた方が断然良いがな
0286デフォルトの名無しさんNGNG
ポインタというか
所有の概念やaliasing、deep/shallow copyみたいなのが
初心者を挫折しやすいんじゃないだろうか
よくはしらないが

どのみち他の言語でも学ばなければならないことだ
Cのポインタの違いはより機械の実装に近いというだけだろう
0287デフォルトの名無しさんNGNG
>>286
逆にポインタを知らないから、浅い/深いコピーとかの違いが分からなくなるんじゃないか?
記述の難しさと、ポインタを意識する/意識しない部分の接合性が上手くいっていないのが、
原因の様な気がする

C は前者、Java は後者 (Java にはポインタなんて用語はねぇがな)
0288デフォルトの名無しさんNGNG
というかそもそもポインタの何がわからんのか
初心者に小一時間問い詰めないと空振りっぽい。
0289デフォルトの名無しさんNGNG
何がわかんないのかわかんない
0290デフォルトの名無しさんNGNG
思うに
「変数は入れ物」の世界から
「値にアドレスでアクセスする」の世界への
対応が出来てねーんじゃねーかと。
0291デフォルトの名無しさんNGNG
Windowsのショートカットみたいなもの
0292デフォルトの名無しさんNGNG
Tronの仮身みたいなもの
0293デフォルトの名無しさんNGNG
Javaはしらんが、C++ならデバッグでメモリウィンドウ見せれば一発だろ
0294デフォルトの名無しさんNGNG
C++ Win32なんだけど、
「thisはC++で定義されているオブジェクト自身へのポインタ」
なんて表記だと煙に巻かれた気がする。
実際
CPaintDC dc(this);
とかはもうイディオムで覚えてるし、これとreturn *this;を除いて、
突然、メンバの呼び出しで使われると困惑するよ。
基本的には変数ポインタと変わらないはずなんだけど、
俺がクラスを分かってないのか

あ、当然、職業プログラマじゃなく勉強中ね。
0295デフォルトでは辛抱たまらんNGNG
そういえば俺ッちもポインタってつまづいた。
非常にインチキな入門書を買ってしまいましてね。
ポインタの説明が数ページしかないの。
「変数箱の荷札」のようなそれはそれは恐ろしい説明であった。
使い道も使用法も意味不明だったし。
マイバイブルとか言っちゃって、
わかんないから何度も何度もよみかえしちゃって、
C言語はむつかしいね〜とか脳みそに植えつけられる結果となった。
0296デフォルトの名無しさんNGNG
http://p44.aaacafe.ne.jp/%7Efeel/
0297デフォルトの名無しさんNGNG
ポインタそのものの説明は難しくないんじゃないか?

ポインタの概念的な説明だけされても、
これが一体何の役に立つのかがわからんから、
初心者は難しく感じるんじゃないかと思う。

ゆえに、ポインタを使わんと解決できない問題を与えるのがいいかと。
0298デフォルトの名無しさんNGNG
ポインタとアドレスの関係は
住所録と住所の関係なり
そんなもんで悩むな
0299デフォルトの名無しさんNGNG
Cを習うのなら基本的なコンピュータのしくみ(概念的な)は勉強しとけってことですな。メモリとアドレスがわかってればポインタを難しいとは思わないはず。プログラミングする上での技巧的な問題はあるけど、それは良質のサンプルソースを提示すりゃ済む問題です。
そういったことを気にせず手軽に使いたいならもっと高級な言語使えばいいことだし。
昔は選択肢がなかったのかもしれないけど、今はCPUも早いし、メモリも大量に積めるし、コンパイラも優秀だし、高級言語でまったく問題ないはず。
0300デフォルトの名無しさんNGNG
>299
>そういったことを気にせず手軽に使いたいならもっと高級な言語使えばいいことだし。

だからこそ、VBがここまで普及してる罠。
0301デフォルトの名無しさんNGNG
>>299
>それは良質のサンプルソースを提示すりゃ済む問題です。

ちょっと分けてもらえませんか?
0302デフォルトの名無しさんNGNG
漏れはポインタが難しいとは思わなかったな。
PCを入手する前に、本で大体覚えたし。
でも本のおかげで、ミスると暴走するというイメージが植え付けられて、
最初は使うのが怖かったな。

苦手意識の何割かは、ポインタの難しさそのものではなく「怖さ」なんじゃないかと思われ。
0303デフォルトの名無しさんNGNG
ポインタが難しいとは思わんが
ポインタを難しいと思っている人には
ポインタを使ったコーディングを(仕事で)
させるのはまずいだろうな
0304デフォルトの名無しさんNGNG
ま、そのへんはCはアセンブラをわかりにくくしたようなもんだししょうがなかんべ
0305デフォルトの名無しさんNGNG
配列が理解できれば、あと一歩だと思うんだが。
0306デフォルトの名無しさんNGNG
あと解説書とかにありがちなんだが、サンプルで完全に完結してない処理を記述するのは
どうかと思う。

学生のころポインタの説明でいきなり定義したポインタに値設定するような記述があったり
して非常に混乱した記憶が。

説明に不必要でも扱ってよい領域をポインタに設定して書き込みを行うという一連の動作に問題ないサンプルソースにするべきだと思ったがどうよ?
0307デフォルトの名無しさんNGNG
日本語お上手ですね
0308デフォルトの名無しさんNGNG
>>307
韓国から出稼ぎにきてる方ですか?
0309デフォルトの名無しさんNGNG
はい、そうです
0310デフォルトの名無しさんNGNG
>>306
そこで「つくわか@void」ですよ。
0311デフォルトの名無しさんNGNG
>>305
配列とポインタを同列で考えると危険じゃなかんべ?
0312デフォルトの名無しさんNGNG
配列をポインタで表現することはできるが
ポインタを配列で表現することは・・・
0313デフォルトの名無しさんNGNG
 ポインタ:地図
これさえあればどこへでもいけるはず……、なんだけど駄目な奴が扱うととんでもないことに。

 参照:カーナビ
上のがよくわかっていない奴にはこっちの方がまだ安心できる(かも)。が、(当たり前だが)完璧に信用できるわけではない。

 ポインタでも参照でもない変数等:駅〜家などよく通る道
言わずもがな。
0314デフォルトの名無しさんNGNG
だから、ポインタと参照の違いを言うなら、ポインタでのアドレス演算が例えれてないとダメなんだよ。
しかもなんだ?完璧に信用できるわけではないって。

紙の地図は更新されないけど、カーナビの地図なら目的地が変われば更新できるしくみがある、という点はその例えでいいけど。
0315デフォルトの名無しさんNGNG
>>313
よけいわからんなるわそれ
0316デフォルトの名無しさんNGNG
>>313
> ポインタでも参照でもない変数等:駅〜家などよく通る道
>言わずもがな。

全然わからん。せめてなにか言ってくれ
0317デフォルトの名無しさんNGNG
[数字の場合]
int a = 5;
int *aP;       int型のアドレスを入れたい時はポインタもint
aP = &a;       を付けると先頭アドレス
printf("%d", *aP);  *を付けると値

[文字の場合]
char a[] = "Hello";
char *aP;       char型のアドレスを入れたい時はポインタもchar
aP = a;        変数名だけで先頭アドレス
printf("%s", *aP);  *を付けると値

ポインタは変数の値を間接参照(アドレスを指定)する時に使う。
変数名, *, & 等ごちゃごちゃ出てくるからややこしくなっているだけ
0318デフォルトの名無しさんNGNG
ポインタとは配列のインデックス番号のことです。
0319デフォルトの名無しさんNGNG
変数へのポインタの場合は、
変数を要素数が1つの配列と考えてください。
0320デフォルトの名無しさんNGNG
文字列は文字の配列と考えてください。
0321デフォルトの名無しさんNGNG
ポインタとは配列のインデックス番号ですが、
通常の配列のインデックス番号が0からはじまるのに対して、
ポインタの場合はメモリ全体を大きな一つの配列とみなしたときの
インデックス番号なので注意してください。
0322デフォルトの名無しさんNGNG
「コンピュータというのは CPU があってメモリがあって CPU にはメモリの位置を示すレジスタがあるのだ」
などという基礎的な観点を礎に「アドレス」という語を使うべきなのか。
それとも「高級言語というのはアーキテクチャを隠蔽してもなお存立できうるべきなのだ」
などという観点から「アドレス」という語を避けるべきなのか。

俺は勉強する順番は基礎からの方がいいと思うんだが、
そんなものを全部飛び越えていきなり C++ やら Java やらやってる即席プログラマもいるわけで、
そういう連中に説明するには後者の方がいいんだろうかなぁ。
0323デフォルトの名無しさんNGNG
禿同。基礎からやれ。まずはCPUの仕組みから。
0324デフォルトの名無しさんNGNG
禿同。基礎からやれ。まずは半導体の仕組みから。
0325デフォルトの名無しさんNGNG
禿同。SQLなんて使うのは5年くらい経験つんでからにしろ。
0326デフォルトの名無しさんNGNG
禿同基礎からやらんと話にならん。







そうおもって、量子力学にまで興味を持ってしまってわけかわらなくなってる今日この頃orz...
廃人になりかけてる気がする...
0327デフォルトの名無しさんNGNG
とまあ、低レベルを基礎だと勘違いしてみるわけだな。
0328デフォルトの名無しさんNGNG
>326
俺も量子力学は良く分からんが
少なくとも難易度では
易:ポインタ<<<<<|越えられない壁|<<<<<<|越えられない壁|<<<<<<量子力学:難
である事は確か
0329デフォルトの名無しさんNGNG
数学の「形式主義」的な立場からすれば、
そこに "矛盾" が生じない限り、
コンピュータの基礎から理解する
必要性は全く生じない筈なんだがな・・・
0330デフォルトの名無しさんNGNG
たとえばデータベースのフロントエンド作る場合、低レベルのことを知っておく必要はほとんどない。
0331デフォルトの名無しさんNGNG
たとえばSEをやる場合、プログラミングの技法を知っておく必要はほとんどない。
■ このスレッドは過去ログ倉庫に格納されています