K.Maebashi's BBS

ご自由に書き込んでください。雑談も可。
テスト書き込みの類はテスト用掲示板にどうぞ

[日付順表示] [日付順インデックス] [スレッド順インデックス]

新規投稿 | 開設者ホームページへ戻る | ヘルプ

[567] ポインタ
投稿者:Java謎+落とし穴読みました
2007/02/20 02:13:25

横からすいません。 Java謎+落とし穴読みました。 なかなか面白い本ですが、ポインタについて少し。 確かにJavaにはポインタがあると考えたほうが理解はしやすいでしょうが、 やはり「厳密に言えば」無いと思います。 まぁ理由はリンクしているページに書いてあるとおりなのですが。 思います、なんて書いてるのは自身がJava仮想マシン仕様書を読んだことが無いからで・・・ リンク先のページに間違いがある可能性もありますが、 説得力で言うとリンク先のページのほうが上かな、と。 まぁどちらも大人な感じを受けますので、 どっちでもいいといえば正直どっちでもいいんですがね^^;
[この投稿を含むスレッドを表示] [この投稿を削除]
[568] Re:ポインタ
投稿者:kei
2007/02/20 02:13:25

>確かにJavaにはポインタがあると考えたほうが理解はしやすいでしょうが、 >やはり「厳密に言えば」無いと思います。 > >まぁ理由はリンクしているページに書いてあるとおりなのですが。 前橋さんのこちらの文章はお読みになりましたか? http://kmaebashi.com/seiha/hosoku001.html 規格上、Cのポインタの内部表現は実装依存で、必ずしもアドレス値であるとは限らないわけです。 リンク先のページは僕も以前読んだ事があって、とてもタメになりました。でも、「Cのポインタはアドレス値」を前提にした説明は変だな、って思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[569] Re:ポインタ
投稿者:Java謎+落とし穴読みました
2007/02/20 02:13:25

>規格上、Cのポインタの内部表現は実装依存で、必ずしもアドレス値であるとは限らないわけです。 >リンク先のページは僕も以前読んだ事があって、とてもタメになりました。でも、「Cのポインタはアドレス値」を前提にした説明は変だな、って思います。 アドレス値を保持する変数という言い方は確かに正確ではないかもしれませんが、 ここで言いたかったのはそういうことではなくて、 「ポインタは最適化できない」ということだと思うのですよ。 (なぜなら「型」という概念上のものだから) C関係の説明は確かに変ですが、そこは言いたかった本質ではないのではないかと。
[この投稿を含むスレッドを表示] [この投稿を削除]
[570] Re:ポインタ
投稿者:kei
2007/02/20 02:13:25

>「ポインタは最適化できない」ということだと思うのですよ。 >(なぜなら「型」という概念上のものだから) すみません、おっしゃっていることがイマイチ掴めません。 >(なぜなら「型」という概念上のものだから) とのことですが、Javaにも「参照型」という概念がありますよね?
[この投稿を含むスレッドを表示] [この投稿を削除]
[571] Re:ポインタ
投稿者:(ぱ)
2007/02/20 02:13:25

>確かにJavaにはポインタがあると考えたほうが理解はしやすいでしょうが、 >やはり「厳密に言えば」無いと思います。 > >まぁ理由はリンクしているページに書いてあるとおりなのですが。 >思います、なんて書いてるのは自身がJava仮想マシン仕様書を読んだことが無いからで・・・ ネットジーンの村山さんの文章ですね。 | Java言語にもJavaVMにも,C言語でいうようなポインタ(pointer) という | 概念は全く存在しない.あるのは参照(reference)であり,参照と | ポインタは異なる概念になる. (中略) | (C言語におけるポインタは単なる「アドレス値を保持する変数」に過ぎない. | Cにおいては配列や文字列さえもポインタ演算で表現されている.これに対して | 参照というのはもっと抽象的な概念で,保持するのがアドレス値であるとは限らない. | 概念が異なるため,例えば「参照どうしの大小関係」や「参照と数値型との相互変換」 | などは,そもそも「定義」することができない. Javaに「アドレス値」としてのポインタは存在しません。そんなことは当たり前で、 そういう意味での「ポインタ」がJavaにあるなどとは誰も主張していないでしょう。 少なくとも私は見たことがありません。村山さんの脳内にはいるのかもしれませんが。 ていうかそもそもCにおいても、ポインタ同士の大小章比較が保証されているのはひとつの 配列内だけだし、ポインタと数値型との相互変換はできますが、それで何が起きるかは 処理系定義なんですが、そういうことをわかって書いてるのかな。 | JavaVMの実装でC言語,及びそのポインタが使われることが多いのは事実だが, (中略) | それは実装依存の話でしかない. 実際、初期の実装では、コンパクションを容易にするために生アドレスではなく オブジェクトハンドルを使っていました。「Java謎+落とし穴」ではそういうことも 書いているわけで(p.131)、私からすれば「だから何?」でしかないです。 | ポインタを「指し示すもの」という一般用語として解釈することも不可能 | ではないが,かなり言い訳じみている. なぜこれが「言い訳じみている」のか、一言も説明してませんね。 PascalやModula2の立場はどうなるのか、とこれも「Java謎+落とし穴~」には 書きました(p.83)。 ところで、村山さんが根拠にしているはずの、JVMの仕様書には以下の記述があります。 http://java.sun.com/docs/books/vmspec/2nd-edition/html/Concepts.doc.html#29375 | There are three kinds of reference types: the class types (§2.8), the | interface types (§2.13), and the array types (§2.15). An object is a | dynamically created class instance or an array. The reference values | (often just references) are pointers to these objects and a special null | reference, which refers to no object. 参照値はポインタだって書いてあるじゃん。
[この投稿を含むスレッドを表示] [この投稿を削除]
[572] Re:ポインタ
投稿者:れぷ
2007/02/20 02:13:25

JVMの仕様書 → 参照はポインタ K&R → ポインタはアドレス ゆえに参照はアドレス ・・・と3段論法にしてしまいますか(^-^;) ↑は冗談としても、ポインタというのはすべからく「データの在り処を指し示すもの」でしかないわけで、Javaの「参照」もC言語のようなポインタではないという風に結論付けてもポインタというのはプログラミング言語にはついて回る概念だと考えています。  それがスタックデータへのポインタであれば「スタックポインタ」ですし、インストラクションデータへのポインタであれば「インストラクションポインタ」でしょう。  参照渡しについて、値渡しとの違いを説明するときにも「データの在り処を渡す」としか説明できないのであれば、それはやはりポインタでしかないと思います。  オライリー本では「参照型はオブジェクトへのハンドル」と説明していますが、仮にハンドラが存在したとしても最終的にはデータの在り処を知る必要が出てきますよね。 # ついでに「C言語で言うとポインタと考えられるでしょう」とも書いてあります。:-)
[この投稿を含むスレッドを表示] [この投稿を削除]
[573] Re:ポインタ
投稿者:(ぱ)
2007/02/20 02:13:25

>JVMの仕様書 → 参照はポインタ > >K&R → ポインタはアドレス > >ゆえに参照はアドレス > > >・・・と3段論法にしてしまいますか(^-^;) 私が言っているのは、 ・Javaのポインタ(参照)は「C/C++の」ポインタとは違う(ところがある)  →Java謎+落とし穴~ 2.1.2「C/C++のポインタとJavaのポインタとの違い」 ・Cのポインタは、必ずしも(生)アドレスである必要はない  →ポインタ完全制覇 2.9 「言語仕様と実装について」 ということなので、村山さんが言うところの、 「JVMはアドレスを使うとは限らんからJavaにはポインタはないのだ」 という批判からすれば、2段階離れたところにいるわけです。 まあ、村山さんの批判対象は、きっと私以外の誰かなのでしょうが。 >↑は冗談としても、ポインタというのはすべからく「データの在り処を >指し示すもの」でしかないわけで、Javaの「参照」もC言語のような >ポインタではないという風に結論付けてもポインタというのはプログラミング >言語にはついて回る概念だと考えています。 そう思います。ただ、もしポインタについて「データの在り処を指し示すもの」 という定義をとらず、「ポインタとはアドレスのことなのだ」という定義の上で 話すのであれば、「Javaにはポインタがない」という主張はあり得ます (そういうこともJava謎+落とし穴~には書きました)。 でもそれを前提にしてくれるな、というのが私の言いたかったことなのでした。 > 参照渡しについて、値渡しとの違いを説明するときにも「データの在り処を >渡す」としか説明できないのであれば、それはやはりポインタでしかないと思います。 うーん、これが関数の引数についてであれば、「参照渡し」はあくまで 「変数引数」の実装手段に過ぎない、と考えれば、これをそこまで言ってしまうのは 実装に過度に踏み込んでいる気もします。 参考リンク: http://java-house.jp/ml/archive/j-h-b/028784.html#body
[この投稿を含むスレッドを表示] [この投稿を削除]
[574] Re:ポインタ
投稿者:れぷ
2007/02/20 02:13:25

> 「JVMはアドレスを使うとは限らんからJavaにはポインタはないのだ」 > という批判からすれば、2段階離れたところにいるわけです。 了解です。 > でもそれを前提にしてくれるな、というのが私の言いたかったことなのでした。 Javaプログラマ達さんのいう「ポインタ」の概念が、 K&Rの「ポインタは、他の変数のアドレスを内容とする変数であり」(p.114)の文章を 前提としているなら「Javaにはポインタがない」という主張はあり得ますね。 ただし、その場合は引用なりすべきだと思います。 > うーん、これが関数の引数についてであれば、「参照渡し」はあくまで > 「変数引数」の実装手段に過ぎない、と考えれば、これをそこまで言ってしまうのは > 実装に過度に踏み込んでいる気もします。 なるほど。ポインタ値ならぬ、「参照値」を引き出した後のことは実装任せということですね。 # 私はまだまだこの辺りの線引きがヘタだなぁ・・・
[この投稿を含むスレッドを表示] [この投稿を削除]
[575] Re:ポインタ
投稿者:(ぱ)
2007/02/20 02:13:25

>うーん、これが関数の引数についてであれば、「参照渡し」はあくまで >「変数引数」の実装手段に過ぎない、と考えれば、これをそこまで言ってしまうのは >実装に過度に踏み込んでいる気もします。 > >参考リンク: >http://java-house.jp/ml/archive/j-h-b/028784.html#body すみません、リンクURL貼り損ねました。正しくはこっちです。 http://java-house.jp/ml/archive/j-h-b/028873.html#body
[この投稿を含むスレッドを表示] [この投稿を削除]
[576] Re:ポインタ
投稿者:(ぱ)
2007/02/20 02:13:25

>> うーん、これが関数の引数についてであれば、「参照渡し」はあくまで >> 「変数引数」の実装手段に過ぎない、と考えれば、これをそこまで言ってしまうのは >> 実装に過度に踏み込んでいる気もします。 >なるほど。ポインタ値ならぬ、「参照値」を引き出した後のことは実装任せと >いうことですね。 ええ、すみません、リンクを貼り損ねたおかげで誤解させてしまったようです。 私が言いたかったのは、貼りなおしたリンク先に http://java-house.jp/ml/archive/j-h-b/028784.html#body | Pascalなどでは、(C系と違って)aの参照と | しての値(アドレス)をどこか他のところへ代入することはできませから、aと | いう参照値の生存範囲はそのスコープ内に限られます。そのような言語では、 | 変数aは呼出し元の変数と「同一物」と考えれば済みます。「元の変数を参照 | している」ということを意識する必要がありません。アドレスが渡されると | いうのは実装上の都合であって、コピーを渡してリターン時に元のところに | コピーし戻すという実装でも同じ意味になります (これをcall-by-value- | resultと呼ぶ)。 とあるように、そもそも単なる変数引数であれば「参照値」自体を意識する 必要はないのではないか、ということです。 まあ、Pascalはともかく少なくともC++では、そういう引数渡しを言語自体が 「参照渡し」と呼んでいるので、ここまで言ってしまうのも問題かもしれませんが、 アプリケーションプログラムを書くのなら、なるべく上の方の世界に住んでいたいなあ、 と私は思うわけでして。
[この投稿を含むスレッドを表示] [この投稿を削除]
[577] Re:ポインタ
投稿者:のぐー
2007/02/20 02:13:25

>| コピーを渡してリターン時に元のところに >| コピーし戻すという実装でも同じ意味になります (これをcall-by-value- >| resultと呼ぶ)。 ここにだけ反応。 これが同じ意味になるのは、pascalにコピーコンストラクタのようなものがないからですよね。もしC++だったら別の意味になってしまいます。 ということで、「コピー渡し」「原本渡し」という言葉を考えてみました。 従来「値渡し」と呼んでいるものは、たいていの場合スタックにコピーが作られるので「コピー渡し」であると。逆に「参照渡し」と呼んでいるものは「原本渡し」であると。 コピーを作るかどうかが意味論上、重要な違いをもつ場合もありますので、 こういう区別って大事だと思うんですが。
[この投稿を含むスレッドを表示] [この投稿を削除]
[578] Re:ポインタ
投稿者:れぷ
2007/02/20 02:13:25

>| いうのは実装上の都合であって、コピーを渡してリターン時に元のところに >| コピーし戻すという実装でも同じ意味になります (これをcall-by-value- >| resultと呼ぶ)。 おお、なるほど! で書かれても実際にはコピーを渡す、という実装のされ方もありえるわけですね。 メモメモ・・・と。 ただ、その場合でも関数から戻ってきた際のコピー先を引数として渡さなくても、 暗黙的にはスタックとかに積んでおく必要がありそうですね。 >アプリケーションプログラムを書くのなら、なるべく上の方の世界に住んでいたいなあ、 >と私は思うわけでして。 あ、これは私も思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[579] Re:ポインタ
投稿者:れぷ
2007/02/20 02:13:25

>ということで、「コピー渡し」「原本渡し」という言葉を考えてみました。 「shallow copy渡し」「deep copy渡し」とか出てきたりして(^-^;)
[この投稿を含むスレッドを表示] [この投稿を削除]
[580] Re:ポインタ
投稿者:(ぱ)
2007/02/20 02:13:25

>これが同じ意味になるのは、pascalにコピーコンストラクタのようなものがないからですよね。もしC++だったら別の意味になってしまいます。 なるほど。それはわかります。 >ということで、「コピー渡し」「原本渡し」という言葉を考えてみました。 >従来「値渡し」と呼んでいるものは、たいていの場合スタックにコピーが作られるので「コピー渡し」であると。逆に「参照渡し」と呼んでいるものは「原本渡し」であると。 なんというか憂鬱本の「実体渡し」を彷彿とさせますが… それはさておき。 「変数引数」的なことをやりたいときに、参照渡しだと、実装上面倒なことに なるケースがあるわけです。たとえばJavaでは、素朴なVMでは、ヒープ中の オブジェクトの先頭以外、ポインタが継続して指すことはありませんが、 参照渡しを許すと、ローカル変数やら、オブジェクトのメンバやら、配列の 要素を指すポインタが継続して保持されてしまう。これは、ガベージコレクタの 実装を考えると何かと面倒です。 そのせいかどうかは知りませんが、Javaは変数引数という機能を言語から 捨て去ってしまった。でも、やっぱりそれじゃswap()も作れないし不便だよね、 という時に、call-by-value-resultという実装方法は効果を発揮するわけです。 Pascal的な言語だと、こうやって実装の楽なGCと変数引数が混在できますが、 コピーコンストラクタを好き勝手に書けるC++だと難しそうではあります。 C#では、=でコピーコンストラクタが動くわけではなかったですよね。確か。
[この投稿を含むスレッドを表示] [この投稿を削除]
[581] Re:ポインタ
投稿者:kit
2007/02/20 02:13:25

>|「元の変数を参照 >| している」ということを意識する必要がありません。アドレスが渡されると >| いうのは実装上の都合であって、コピーを渡してリターン時に元のところに >| コピーし戻すという実装でも同じ意味になります (これをcall-by-value- >| resultと呼ぶ)。 > >とあるように、そもそも単なる変数引数であれば「参照値」自体を意識する >必要はないのではないか、ということです。 話は完全にそれますが、この JavaHouse での記述は誤りですね。 var x:integer; procedure hoge(var a: interger); begin a:=1; a:=a+x; end; x:=10; hoge(x); のように、変数引数が alias となるケースでは、参照渡しの場合と、 call-by-value-result 場合とで結果が異なります。 参照渡し: x=2 call-by-value-result: x=11 参照値であるということを意識しないですむとは限りません。
[この投稿を含むスレッドを表示] [この投稿を削除]
[582] Re:ポインタ
投稿者:(ぱ)
2007/02/20 02:13:25

まずお詫びと訂正ですが、[575]でURLの訂正をしましたけれど、 [576]でまた間違ったほうのURLを貼ってしまいました。正しいのは http://java-house.jp/ml/archive/j-h-b/028873.html#body です。 >話は完全にそれますが、この JavaHouse での記述は誤りですね。 そうでした。(完璧に意識の外でしたが)Pascalではprocedureのネストが可能で、 呼ばれた側の関数から呼び出し側の関数のローカル変数を参照できるため、 呼び出し側の関数のローカル変数がいつ変更されたのかが見えてしまうわけですね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[583] Re:ポインタ
投稿者:(ぱ)
2007/02/20 02:13:25

>ただ、その場合でも関数から戻ってきた際のコピー先を引数として渡さなくても、 >暗黙的にはスタックとかに積んでおく必要がありそうですね。 呼び出し側で、通常の値渡しと同じように現状の値をスタックに積み、 関数から戻って来たところで、呼び出し側でコピーを行えばよいのでは。
[この投稿を含むスレッドを表示] [この投稿を削除]
[584] Re:ポインタ
投稿者:れぷ
2007/02/20 02:13:25

>呼び出し側で、通常の値渡しと同じように現状の値をスタックに積み、 >関数から戻って来たところで、呼び出し側でコピーを行えばよいのでは。 そうですそうです。 なので「コピー先(元)がどこ?」って情報がどこかには必要ですよね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[585] Re:ポインタ
投稿者:(ぱ)
2007/02/20 02:13:25

>>呼び出し側で、通常の値渡しと同じように現状の値をスタックに積み、 >>関数から戻って来たところで、呼び出し側でコピーを行えばよいのでは。 >そうですそうです。 >なので「コピー先(元)がどこ?」って情報がどこかには必要ですよね。 ええと、C(C++?)風擬似言語で、 void hoge(int &a) ←変数引数の宣言 { printf("%d", a); a = 10; } int main() { int b = 20; hoge(b); } と書いたとき、 (1)通常のCの関数呼び出しと同様、main側で、bをスタックに積む。 (2)よって、hoge()のprintf()では、20が表示される。 (3)hoge()内の「a = 10;」により、引数aに10が設定されて、リターン。 さて、リターンした後ですが、main()側は、aとb両方のアドレスを 知っているわけです。なので、bのアドレスをスタックなどに積む必要は ないのでは、と言いたかったわけですが。
[この投稿を含むスレッドを表示] [この投稿を削除]
[586] Re:ポインタ
投稿者:のぐー
2007/02/20 02:13:25

>Pascalではprocedureのネストが可能で、 >呼ばれた側の関数から呼び出し側の関数のローカル変数を参照できるため、 C言語に変数引数を追加した言語でも、グローバル変数を使えば同じことが起きませんか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[587] Re:ポインタ
投稿者:(ぱ)
2007/02/20 02:13:25

>>Pascalではprocedureのネストが可能で、 >>呼ばれた側の関数から呼び出し側の関数のローカル変数を参照できるため、 > >C言語に変数引数を追加した言語でも、グローバル変数を使えば同じことが起きませんか? あ、そりゃそうだ f(^^; いろいろ見逃してましたね。ご指摘ありがとうございます。
[この投稿を含むスレッドを表示] [この投稿を削除]
[588] Re:ポインタ
投稿者:れぷ
2007/02/20 02:13:25

>さて、リターンした後ですが、main()側は、aとb両方のアドレスを >知っているわけです。なので、bのアドレスをスタックなどに積む必要は >ないのでは、と言いたかったわけですが。 なるほど(^-^;) 了解です。
[この投稿を含むスレッドを表示] [この投稿を削除]