K.Maebashi's BBS

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

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

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

[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++では、そういう引数渡しを言語自体が 「参照渡し」と呼んでいるので、ここまで言ってしまうのも問題かもしれませんが、 アプリケーションプログラムを書くのなら、なるべく上の方の世界に住んでいたいなあ、 と私は思うわけでして。
[この投稿を含むスレッドを表示] [この投稿を削除]
[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
[この投稿を含むスレッドを表示] [この投稿を削除]
[574] Re:ポインタ
投稿者:れぷ
2007/02/20 02:13:25

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

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

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

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

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

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

あーなんか誤解を招きかねない?のでちょっと修正 malloc 等で得られたポインタ値が prm に入っているとします (仮に 0xabcd としよう) free(prm); する前の時点では prm==0xabcd であり 0xabcd 番地のメモリを使うことができます。 free(prm); した後の時点でも prm==0xabcd ですが 0xabcd 番地のメモリは使えなくなっています。 ってただそれだけの話ですね。 # 厳密に言えば 0xabcd 番地にメモリはあるが、使用権限が無いというべきか。 free(prm); の後に free(prm->cpItem); のような操作をしてはいけません。 free(prm); した時点で prm の指す先は無効となっています。 こういうのをダングリングポインタとか言いますな。
[この投稿を含むスレッドを表示] [この投稿を削除]
[565] Re:reallocについて
投稿者:774RR
2007/02/20 02:13:25

prm が指す先のメモリ領域は正しく開放されます。 その結果 prm 自体は無効なメモリ領域を指すようになるだけです。 まったく一切何の問題もありません。 >引数を変更しても呼び出し元には影響を与えないように思います。 そこのところはまさに御意なのですが、 どこで「prm そのもの」を操作しているのでしょうか? prm が指す先を操作しているだけです。 ごくふつーに、配列等で行っている処理とまったく同じ事をしていますよ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[564] Re:reallocについて
投稿者:SEC
2007/02/20 02:13:25

>正>void PrmDestroy( typChangePrm *prm) >正>{ >正> int i; >正> >正> if ( prm && prm->cpItem) { >正> for ( i=0; i<prm->itemCount; i++) { >正> free(prm->cpItem[i]); >正> } >正> } >正> if ( prm) free(prm->cpItem); >正> free(prm); >正>} 上記関数のfree(prm);の部分ですが、 この処理でprmはきちんと開放されているのでしょうか。 Cの引数は値渡しなので、(この場合、引数はポインタですが、ポインタも値渡し) 引数を変更しても呼び出し元には影響を与えないように思います。 free(prm->cpItem);のように、ポインタの中身に対する変更は問題ないと思います。
[この投稿を含むスレッドを表示] [この投稿を削除]
[563] Re:aaaaa
投稿者:(ぱ)
2007/02/20 02:13:25

>aaaaaa 上に書いてあるように、テスト書き込みならテスト掲示板の方にお願いします。
[この投稿を含むスレッドを表示] [この投稿を削除]
[562] Re:大したことではないのですが
投稿者:(ぱ)
2007/02/20 02:13:25

>http://kmaebashi.com/programmer/devlang/yacclex.html 上のyaccfile.png >という画像の説明において、mycalc.l → yacc となっているのが気になりました >(mycalc.y → yacc ですよね?間違っていたらゴメンナサイ)。 ご指摘ありがとうございます。 おっしゃるとおり間違っていますので、修正しました。ありがとうございました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[561] aaaaa
投稿者:yosyyi
2007/02/20 02:13:25

aaaaaa
[この投稿を含むスレッドを表示] [この投稿を削除]
[560] aaaaa
投稿者:yosyyi
2007/02/20 02:13:25

aaaaaa
[この投稿を含むスレッドを表示] [この投稿を削除]
[559] 大したことではないのですが
投稿者:hajimemasite
2007/02/20 02:13:25

はじめまして。 yacc/lex の解説ページを探していてたどり着きました。 説明がわかりやすくて助かります。 http://kmaebashi.com/programmer/devlang/yacclex.html 上のyaccfile.png という画像の説明において、mycalc.l → yacc となっているのが気になりました (mycalc.y → yacc ですよね?間違っていたらゴメンナサイ)。 これからも頑張ってください。
[この投稿を含むスレッドを表示] [この投稿を削除]
[558] Re:reallocについて
投稿者:れぷ
2007/02/20 02:13:25

>大変失礼しました。私の能力の低さが露呈してます(T-T) ぐぁっ、私はそこって全然気がつきませんでした(T_T)
[この投稿を含むスレッドを表示] [この投稿を削除]
[557] Re:reallocについて
投稿者:れぷ
2007/02/20 02:13:25

>とはいえいわゆる non-ANSI な超古い処理系ではダメなのもあったような記憶がうっすらと。 あ、non-ANSIは知らないです。いわゆる「ぬるぽ」になるかもしれませんね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[556] Re:reallocについて
投稿者:774RR
2007/02/20 02:13:25

>>free() の解説に、空ポインタの場合何もしないとあるので無問題です。 >C89もセーフですよ。 とはいえいわゆる non-ANSI な超古い処理系ではダメなのもあったような記憶がうっすらと。 そーいう化石のようなプラットフォームまで考えるかどうか次第かな。
[この投稿を含むスレッドを表示] [この投稿を削除]
[555] Re:reallocについて
投稿者:本多
2007/02/20 02:13:25

>>>free() の解説に、空ポインタの場合何もしないとあるので無問題です。 >>C89もセーフですよ。 確かにfree(NULL)は無問題なのですが、以下の※の箇所は大問題でした。 | if ( (prm = malloc( sizeof( typChangePrm))) == NULL) { | fprintf(stderr,"ERROR: memory allocation\n"); | goto LERROR; ←ココ | } (中略) | LERROR: | free( prm->cpItem); ← ※ | free( prm); | return NULL; |} このような箇所は「if ( prm ) free( prm->cpItem);」が必要ですね。 以下の箇所も間違っていますね。 誤>void PrmDestroy( typChangePrm *prm) 誤>{ 誤> int i; 誤> 誤> for ( i=0; i<prm->itemCount; i++) 誤> free(prm->cpItem); 誤> free(prm->cpItem); 誤> free(prm); 誤>} 正>void PrmDestroy( typChangePrm *prm) 正>{ 正> int i; 正> 正> if ( prm && prm->cpItem) { 正> for ( i=0; i<prm->itemCount; i++) { 正> free(prm->cpItem[i]); 正> } 正> } 正> if ( prm) free(prm->cpItem); 正> free(prm); 正>} 大変失礼しました。私の能力の低さが露呈してます(T-T)
[この投稿を含むスレッドを表示] [この投稿を削除]
[554] Re:reallocについて
投稿者:れぷ
2007/02/20 02:13:25

>realloc() に失敗する状況でどうリカバリーするかの仕様次第ですけど、 >書かない癖つけたほうがいいと思う。 私もそう思います。 なので私のサンプルはメモリの再配置が多そうだったことも含めて 完全にfree()してしまったりしてます(^-^;)
[この投稿を含むスレッドを表示] [この投稿を削除]
[553] Re:reallocについて
投稿者:れぷ
2007/02/20 02:13:25

>free() の解説に、空ポインタの場合何もしないとあるので無問題です。 C89もセーフですよ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[552] Re:reallocについて
投稿者:774RR
2007/02/20 02:13:25

>矢印の箇所でgotoしたとき、prmはNULLだからSegmentation faultになりませんか。 C89 でどうだったかは知りませんが少なくとも C99 では free() の解説に、空ポインタの場合何もしないとあるので無問題です。 MSDN や HPUX11.00 の man にも同一の旨の記述があります。
[この投稿を含むスレッドを表示] [この投稿を削除]
[551] Re:reallocについて
投稿者:(ぱ)
2007/02/20 02:13:25

>typChangePrm *CreatePrm( char *cString, int itemCount) >{ > typChangePrm *prm = NULL; > int i; > > if ( (prm = malloc( sizeof( typChangePrm))) == NULL) { > fprintf(stderr,"ERROR: memory allocation\n"); > goto LERROR; ←ココ > } (中略) > LERROR: > free( prm->cpItem); > free( prm); > return NULL; >} 矢印の箇所でgotoしたとき、prmはNULLだからSegmentation faultになりませんか。
[この投稿を含むスレッドを表示] [この投稿を削除]
[550] Re:reallocについて
投稿者:本多
2007/02/20 02:13:25

こんな感じかなぁ? 要素追加しちゃったけど。 ---- #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct{ int itemCount; char cString[50]; char **cpItem; } typChangePrm; typChangePrm *CreatePrm( char *cString, int itemCount) { typChangePrm *prm = NULL; int i; if ( (prm = malloc( sizeof( typChangePrm))) == NULL) { fprintf(stderr,"ERROR: memory allocation\n"); goto LERROR; } if ( strlen( cString) >= 50 ) return NULL; strcpy( prm->cString, cString); prm->itemCount = itemCount; if ( (prm->cpItem = malloc( sizeof(char *) * itemCount )) == NULL) { fprintf(stderr,"ERROR: memory allocation\n"); goto LERROR; } for ( i=0; i<itemCount; i++) prm->cpItem[i] = NULL; return prm; LERROR: free( prm->cpItem); free( prm); return NULL; } void PrmDestroy( typChangePrm *prm) { int i; for ( i=0; i<prm->itemCount; i++) free(prm->cpItem); free(prm->cpItem); free(prm); } void PrmResize( typChangePrm *prm, int itemCount) { char **tmp; int i; if ( prm->itemCount >= itemCount ) { for ( i=itemCount; prm->i<itemCount; i++) free( prm->cpItem[i]); prm->itemCount = itemCount; return; } tmp = prm->cpItem; if ( (tmp = realloc( tmp, sizeof(char *) * itemCount)) == NULL) { fprintf(stderr,"ERROR: memory allocation\n"); goto LERROR; } prm->cpItem = tmp; for ( i=prm->itemCount; i<itemCount; i++) prm->cpItem[i] = NULL; prm->itemCount = itemCount; return; LERROR: free( prm->cpItem); } void PrmSetItem( typChangePrm *prm, int item_no, char *item) { if ( item_no >= prm->itemCount) return; if ( (prm->cpItem[ item_no] = strdup( item)) == NULL) fprintf(stderr,"ERROR:memory allocation\n"); } void PrmShow( typChangePrm *prm) { int i; printf("********************************\n"); printf("Item Count:%d\n",prm->itemCount); printf("cString :%s\n",prm->cString); for ( i=0; i<prm->itemCount; i++) printf("Item[%d]:%s\n",i,((prm->cpItem[i]==NULL)?"NULL":prm->cpItem[i])); } int main(void) { typChangePrm *prm; char *item[] = { "hello", "world", "program"}; if ( (prm = CreatePrm("c-string",2)) == NULL) return 1; PrmSetItem(prm,0,item[0]); PrmSetItem(prm,1,item[1]); PrmShow( prm); PrmResize( prm, 3); PrmSetItem(prm,2,item[2]); PrmShow( prm); PrmResize( prm, 1); PrmShow( prm); PrmDestroy(prm); return 0; }
[この投稿を含むスレッドを表示] [この投稿を削除]
[548] Re:reallocについて
投稿者:774RR
2007/02/20 02:13:25

>data.cpItem[n] = realloc( data.cpItem[n], new_size); 皆さん同じコードをかかれていますけど、これってダメコードですよ。 realloc() に失敗したら、旧 data.cpItem[n] がリークしますね。 # 旧値が失われて復旧の手段が無い。 realloc() に失敗する状況でどうリカバリーするかの仕様次第ですけど、 書かない癖つけたほうがいいと思う。
[この投稿を含むスレッドを表示] [この投稿を削除]
[547] Re:reallocについて
投稿者:本多
2007/02/20 02:13:25

>要はコダマンさんが、 > ・cpItem自体をreallocしたいのか > ・cpItem[n]のほうをreallocしたいのか >に尽きるんじゃないでしょうか。 要求をちゃんと定義してもらわずに作業を始めると戻り工数が大きくなりますよねー 私は最初「構造体の中のポインタ配列のreallocの方法」と言ってるので typedef struct{ char cString[50]; char *cpItem[]; }typChangePrm; typChangePrm data; data.cpItem[n] = realloc( data.cpItem[n], new_size); の程度のことを質問してると思ってましたが...(^^) 日本語の解釈って色々できるんですね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[546] Re:reallocについて
投稿者:れぷ
2007/02/20 02:13:25

要はコダマンさんが、  ・cpItem自体をreallocしたいのか  ・cpItem[n]のほうをreallocしたいのか に尽きるんじゃないでしょうか。 まきじさんのサンプルは前者をrealloc()ですけれど、 後者も行いたい場合はやはりこちらもrealloc()で書いたほうが便利でしょうね。 # あとcpItem自体が縮小した場合の考慮をしないとメモリリークしますね。 # ってここはツッコミ入れなくても大丈夫か(^-^;)
[この投稿を含むスレッドを表示] [この投稿を削除]