[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[jfriends] Re: ポインターと参照




前橋です。

ちょっと順番変えてます。

天野さん:
>以前、遠藤さんが、「ポインターはアドレスではない」発言に
>「えっ」と思ったのでかなり根本的な部分だったりするのでしょ
>うが、質問しました。

私もやっぱり、「ポインタはアドレスではない」と思っています。

以下、私の考え方です。間違い・異論等ありましたら御指摘ください。

確かに、native なC言語では、「ポインタ」と呼ばれる領域にはア
ドレスが格納されています。でも、それは、ポインタを実現するた
めにC言語が使用している *手段* に過ぎず、ポインタという概念
は、もう少し高レベルのものであると考えるからです。

意味的には、「ポインタ」とは、「何かを指し示すモノ」です。

例えば、連結リストやツリーを構築するためには、ポインタが必要
です。連結リストなら、次の要素を指し示す必要があるからです。

で、ポインタのない、FORTRAN77のような言語では、配列の添字を
使ったりするわけです。これは、プログラミング言語レベルでは、
単なる整数ですが、アプリケーションプログラムでは、意味的に
ポインタであると考えられます。

つまり、言語がポインタをサポートしてくれていないので、プログ
ラマが泥をかぶって、ポインタを実現してやるわけです。

C/C++では、言語がポインタを提供してくれています。

C/C++では、それを実現するために、たまたまアドレスを生で使っ
ています(これも所詮仮想アドレスだから生じゃないかもしれんけど)。
でも、だからといって、アプリケーションプログラマが、それを
「アドレス」であると認識する必要はないはずです。手段はどうやっ
てるのかわからんけれど、とにかく、「何かを指し示すモノ」です。

我らが Javaでは、オブジェクトは、オブジェクトの実体を指し示
すモノですから、これはやっぱりポインタであると私は考えます。

でも、このポインタは、動作するCPU上のアドレスをそのまま使っ
ているとは限りません。確か、Sunの実行系では、ガベージコレク
ションのうちのコンパクションを平行して行なうために、ポインタ
は間接参照テーブルを経由していた筈です(つまり、ポインタのポ
インタ)。MicrosoftのJVMは、GCが複写式なので、また違う実現方
法になっているでしょう。でも、そんなことは、我々アプリケーショ
ンプログラマにとっては、「知ったこっちゃない」話です。

まとめると、

・アプリケーションプログラム層
・プログラミング言語層
・機械語層

みたいなレイヤ分けがあって、

FORTRANでは、プログラミング言語層にポインタがないので、アプ
リケーションプログラム層でポインタを実現してやる。

C/C++では、プログラミング言語層でポインタを提供してくれてい
る。その実現手段は、機械語層(?)のアドレスそのものである。

Javaでは、プログラミング言語層でポインタを提供してくれている。
その実現手段は、隠蔽されていて、アプリケーションプログラマは
意識する必要がない。

# でも、ポインタを意味的に捉えるより、さっくりアドレスだと思っ
# た方が、初心者のとっつきは良いと思います。Cを教える時に、
# 「ポインタはアドレスだよん」と教えるか、最初から矢印で教え
# るかは難しい所かも知れませんが、私は「アドレスだよん」から
# 入ってもいい(というか、その必要がある)と思います。でも、い
# つかは、矢印であるという理解に至らないと。

余談:
Cでも、プロセスをまたがったりして、直接ポインタで指せないも
ののために、意味的なポインタを作ることはありますよね。例えば、
UNIXのファイルディスクリプタは単なる整数型ですが、意味的には
ポインタです。その証拠(?)に、代入しても実体は複製されません。
dup()をコールする必要があります。まさにclone()です。X-Window
のウィンドウ識別子、Windowsのハンドルなんかもそうですよね。

>あまりに複雑な部分なので、説明のしようがないと思いますから、
>皆さんに迷惑かける訳にもいきませんので「ここが理解しやすいサイト」
>とか、この本がわかりやすいなどの情報が欲しいです。

こういう場合、「ポインタでいいですから教えてください」という
言い方があったりします :-)

さて...

>ポインター = メモリーアドレスが入っている。つまりデータではない

というわけで、ポインタには、必ずしもアドレスが入っている必要
はありません。C/C++ではアドレスが入っているけれど。

>Java の参照と C++ の参照は違うらしい。 -> どう違うのか?

これは違います。Javaの参照は、C/C++で言う所のポインタです。

ただし、違いはあって、

・Javaでは、& も * もないので、基本型(プリミティブ)のポイン
  タを取得することはできない。
・Javaでは、オブジェクトは常にポインタである。

何故こうなっているのか?

...VM(GC)の実装を簡単にするため、に見えるのは私だけ?

C++の参照については、既に何人かの方が書いておられるので省略
します。

>ポインターと参照が同じならば表記法が違うのはなぜ? 

C++では違うから表記法が違うわけでして。

Javaの場合、オブジェクトはどうせポインタしかないから、わざわざ
長ったらしく -> を使わなくても . で事足りるということでしょう。
意味的には、Javaの . って、Cの -> なんだけど。

>オブジェクト = 構造体 + 関数へのポインタ

むー。実装上、メソッドが10も20もあるオブジェクトについて、オ
ブジェクト毎にメソッドへのポインタを持たせたらかさばってしょ
うがないので、実際には、

オブジェクト = 構造体 + クラスの定義体へのポインタ

だと思いますが。

# でも、それも、アプリケーションプログラマが意識すべき話では
# ないような気もします。
## でも、一度は意識しないと理解が困難なような気もするのでした。

>オブジェクトの参照 =  オブジェクトのデータが順番に入っている
>			メモリー領域の先頭アドレス。

前述のように、これはそうとは限りません。

tiny Javaでいいから、一度コンパイラと実行系を書いてみようかと
思っている今日このごろなのでした。でも、時間ないんだよなあ...

------------------------------------------------------------
  前橋 和弥                             maebashi@xxxxxxxxxx
  中部ソフトエンジニアリング(株)
    〒450 名古屋市中村区名駅4-10-25(名駅IMAIビル 5F)
    Tel:(052)583-4511(代) 内線 252 Fax:(052)583-4566
------------------------------------------------------------