K.Maebashi's BBS

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

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

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

[1086] Re:変数の宣言
投稿者:ひげおやじ
2008/02/06 00:19:01

たいへん丁寧なご説明ありがとうございます。感謝しております。 未だ「処理系の実装」を想像できるほど物を知っているわけでは ないのですが、理解を深めるのに意識しながら今後勉強して行きたいと 思います。 ちなみに、メモリを意識せずにプログラミングを自力で作成できるように なるのが良いのかもしれませんが、Javaでの継承がメモリモデルを使って 解説してある記事 http://www.atmarkit.co.jp/fjava/rensai2/javaent04/javaent04.html などを読むと、意識すると理解がより深まるのかなぁ、なんて最近思っています。 大学生に教える機会が多いのですが、何をどの程度教えればよいか、 こんなことを気に留めながら、試行錯誤しています。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1085] Re:変数の宣言
投稿者:(ぱ)こと管理人
2008/02/04 01:35:25

>>このへんから、 >>・静的型言語 >>・実行時に型を持つ言語 >>・アセンブラみたいな、本当に型のない言語 >>あたりの対比につながると面白いのかな、と思いつつ、 ええと、すみません、そんなたいした話ではないのですが。 たとえばCで、 int a; という(定義を兼ねた)宣言があったとき、これは >(1)変数xの内容を読んだり書いたりするときには、型Tに合った メモリの使い方に従います。 >(2)(1)、かつ、変数xのメモリ領域を型Tに対応するサイズだけ確保する。 この(1), (2)の両方を意味しますが、(1)の意味で効いてくるのはコンパイル時であり、(2)は実行時なんですよね(細かく言えば、staticでないローカル変数なら関数突入時、グローバル変数なら実行開始時)。 もちろんCではintとdoubleとでは普通はサイズが違いますから、「型Tに対応するサイズだけ確保する」ためには型を知らなければならないように思いますが、実際には「intのローカル変数ふたつ」であっても「doubleのローカル変数ひとつ」であっても、実行時の機械語コードは「スタックに領域を8バイト分確保する」となっている(※1)だけで、細かい型までは意識していません。 構造体定義にしても、 typedef struct { double x; double y; } Point; と書いたとして、Cでは、この型定義の情報はコンパイルされた機械語コードには残っていません。Point型の変数pがあったとき、p.yという記述は、「pの先頭アドレスから8バイト(※1)ずれたところを参照する」という機械語コードに変換されるのであって、「メンバyを参照する」ということは実行時には意識していません。 Javaあたりだと微妙に話が違って、リフレクション用にクラスの情報を保持しておく必要はありますし、バイトコード中に「メンバy」という情報は残っていますが、「メンバy」という情報はロード時にオフセット参照に変換されるはずです(JITがなかったとしても)。 静的型言語だとこんな感じですが、型なし言語であるRubyとかcrowbarでは、 a = 10; で変数が宣言されます。JavaScriptなら var a; でしょうか。これはひげおやじさんのおっしゃるところの(2)を、実行時に行っています(※2)。ただし「a = 10;」の実行のあとで「a = "abc";」と書くのも許されます。これは、整数型も文字列型も(変数aのレベルでは)同じサイズで表現されるためです。また、オブジェクトのメンバを参照するためa.yと書いてあったとき、aの型は実行時までわかりません(aにyというメンバがあるかどうかさえも)。よってひげおやじさんがおっしゃるところの(1)は、aという変数が宣言されたさらに後、まさにその変数を使うときに判定されるわけです。 「アセンブラみたいな、本当に型のない言語」は、例としてはたとえば(Cの前身である)Bなんかがそうでしょう。Bでは auto a; で変数が宣言できるようですが(※3)、なにしろBには型がないというか、intとポインタ(アドレス)は同じ型でそれ以外の型はなかったわけですから、「auto a;」は(2)の意味しか持ち得ません。 ……ええと、なんというかあまり面白い話にはならなかった気がしますが、ひげおやじさんもおそらく哲学論議がしたいわけではないと思いますから、ここはひとつ「言語を作ってみる」…とまではいかなくても処理系の実装を想像してみる、というのはいかがでしょうか(と、「プログラミング言語を作る」の宣伝につなげてみる)。 とか言いつつ、静的言語であるDiksamは、いまだにクラス部分が公開できてないわけですが。秋ごろから一応クラスやポリモルフィズムは動いていて、ただいろいろな意味で中身がぐちゃぐちゃで、作業時間が全然(本当に全然)取れないので進んでいないのですが。 ※1)intが4バイト、doubleが8バイトの処理系を想定しています。 ※2)Rubyの変数の宣言は厳密には「代入文が実行されたとき」ではないのですが、ここでは置いておきます。 ※3) http://cm.bell-labs.com/cm/cs/who/dmr/kbman.html
[この投稿を含むスレッドを表示] [この投稿を削除]
[1084] Re:変数の宣言
投稿者:ひげおやじ
2008/02/02 15:56:57

ご返答ありがとうございます。 >なんというか、ご質問は、その指すところが曖昧で、(失礼ながら)初心者がワケわかんなくなった上での質問のように一見すると見えて、「774RRさんいきなりそんな話をされても」とか書くべきかと酔っ払った頭で一瞬思ったのですが。 まさにその初心者で、自分で頭の整理ができなくて質問してしまったようなところです。 結局は、変数の「宣言」と「定義」の違いをきちんと認識するのが不足していた と自分では省みています。(質問にもその認識不足がにじみでていたな、とも。) それだけではないのかもしれませんが・・・。 >ヒントになるかもしれないこととしては、 > >typedef struct { > double x; > double y; >} Point; > >と書いたとき、これだけでは単なる型宣言なのでメモリはまったく確保しませんが、上記(1)で言うところの型Tを定義する意味は持っているわけですよね。 これって、Javaのabstract class や interfaceなどでも同じことが当てはまるんでしょうか。浅はかな知識だけで、この質問も曖昧かもしれなく、すいません。 >このへんから、 >・静的型言語 >・実行時に型を持つ言語 >・アセンブラみたいな、本当に型のない言語 >あたりの対比につながると面白いのかな、と思いつつ、 可能ならば、この続きを教えていただければと存じます、触りだけでも。 宜しくお願い致します。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1083] Re:変数の宣言
投稿者:(ぱ)こと管理人
2008/02/02 05:43:38

どうもです。 >プログラムで、変数を宣言する文は、プログラムを実行した >ときのパソコンのどんな動作に対応するのでしょうか。 なんというか、ご質問は、その指すところが曖昧で、(失礼ながら)初心者がワケわかんなくなった上での質問のように一見すると見えて、「774RRさんいきなりそんな話をされても」とか書くべきかと酔っ払った頭で一瞬思ったのですが。 >(1)変数xの内容を読んだり書いたりするときには、型Tに合った >メモリの使い方に従います。 >(2)(1)、かつ、変数xのメモリ領域を型Tに対応するサイズだけ確保する。 この(1)と(2)は、変数の宣言の二面性をかなり明確に意識しているように思います(だからこそ774RRさんのご回答がこの区分にきっちり一致しているわけで)。 今は酔っ払っているので頭回ってませんが、ヒントになるかもしれないこととしては、 typedef struct { double x; double y; } Point; と書いたとき、これだけでは単なる型宣言なのでメモリはまったく確保しませんが、上記(1)で言うところの型Tを定義する意味は持っているわけですよね。 このへんから、 ・静的型言語 ・実行時に型を持つ言語 ・アセンブラみたいな、本当に型のない言語 あたりの対比につながると面白いのかな、と思いつつ、すみませんもう寝ますおやすみなさい。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1082] Re:変数の宣言
投稿者:774RR
2008/02/01 22:20:46

>また、言語によって違ったりするんでしょうか。 世の中にはプログラミング言語など星の数ほどあるので、違ったりするだろうな それだと答えに困るので、とりあえず C C++ の類に限定すると メモリ という言葉をより広義の「記憶域」と読み替えて (1) Yes (2) 宣言が同時に定義となる場合には Yes 変数は狭義の「メモリ」つまり、俗に言う RAM に置かれるとは限らなくて もっと高速にアクセスできる「レジスタ」に置かれる場合もあるわけだ。 レジスタとメモリ(とその他変数に使えそうなもの)を称して記憶域という (1)(2)のあわせ技から以下のようなバグが発生することがあるので注意だな 「定義にならない宣言」と「定義になる宣言」が矛盾する場合におかしなことになる ---a.c--- extern int wrong_declared_variable; // declaration without definition ... wrong_declared_variable=0; // may destroy other variables ---b.c--- char wrong_declared_variable; // declaration with definition
[この投稿を含むスレッドを表示] [この投稿を削除]
[1081] 変数の宣言
投稿者:ひげおやじ
2008/01/31 20:39:14

お世話になります。 プログラムで、変数を宣言する文は、プログラムを実行した ときのパソコンのどんな動作に対応するのでしょうか。 変数xをある型Tで宣言するのは、次のいずれかなんじゃないかなぁ、 なんて自分では推測しているのですが。 (1)変数xの内容を読んだり書いたりするときには、型Tに合った メモリの使い方に従います。 (2)(1)、かつ、変数xのメモリ領域を型Tに対応するサイズだけ確保する。 (3)(1)、(2)以外。 どれが正解なんでしょう。それとも正解はないんですかね(^_^; また、言語によって違ったりするんでしょうか。 どなたかご教授いただければ幸いです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1079] Re:「ほげほげ認証」てすと
投稿者:(ぱ)こと管理人
2008/01/11 01:16:12

>本日は晴天なり すみません、純粋なテスト投稿であればできるだけテスト用掲示板 http://kmaebashi.com/bbs/list.php?boardid=testbbs の方にお願いします。テスト用掲示板にもほげほげ認証は付いています。 …が、今見てみたら、テスト用掲示板にはspamが来てるじゃないですか! 人間がアルバイトで投稿しているのかなあ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1078] 「ほげほげ認証」てすと
投稿者:
2008/01/10 19:09:28

本日は晴天なり
[この投稿を含むスレッドを表示] [この投稿を削除]
[1077] Re:業務連絡:「ほげほげ認証」を実装しました
投稿者:(ぱ)こと管理人
2008/01/03 09:35:50

>では早速テスト投稿などしてみませう どうも、おひさしぶりです。 # おひさしぶりになってしまったのは掲示板が壊れていたためですね…すみません。 >はたして cgi 君はうまくうごくのであろうか PHPだからcgiではないです、というツッコミはありでしょうか。 ところで、昨日は一晩で14通のspamが来たことを考えると、「ほげほげ認証」は それなりに効果があると思ってよさそうです。もうちょっと続けてみないと なんとも言えませんが。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1076] Re:業務連絡:「ほげほげ認証」を実装しました
投稿者:774RR
2008/01/02 18:56:17

では早速テスト投稿などしてみませう はたして cgi 君はうまくうごくのであろうか
[この投稿を含むスレッドを表示] [この投稿を削除]
[1075] 業務連絡:「ほげほげ認証」を実装しました
投稿者:(ぱ)こと管理人
2008/01/02 16:37:11

掲示板を直したところspamがひどいので、 以下のページで紹介されている「ほげほげ認証」を導入しました。 http://diary.noasobi.net/2006/07/diary_060728a.html お手数をおかけしますが、今後投稿する際は、投稿欄の下のテキストボックスに 「ほげほげ」と入力してください。 こんなのは固定パスワードですし、画面に堂々と出るわけですし、 本来であればCAPTCHAか何かを導入すべきかもしれませんが、 ロボット相手ならそれなりに効果があるんじゃないかなあ、ということで 手抜き実装です。 投稿される方にはひと手間増えて申し訳ありませんが、よろしくお願いいたします。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1074] Re:あけましておめでとうございます(兼業務連絡)
投稿者:(ぱ)こと管理人
2008/01/02 07:33:44

>max(serialid)に置き換えて修復しました。 > >どうりで長いこと投稿がなかったわけだ… で、直したとたんスパム14連発かよ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1073] あけましておめでとうございます(兼業務連絡)
投稿者:(ぱ)こと管理人
2008/01/01 16:37:06

今年もよろしくお願いいたします。 ……と投稿しようと思ったら、SQLがエラーを吐きました。 スクリプトを見直したら、掲示板ごとの連番を取得するところでcount(*)を使っており、 少し前の広告削除で空き番ができるような物理削除をしていたのでcount(*)で取得した 連番が重複エラーを出していました。センスの悪いSQLを書いてましたね。 max(serialid)に置き換えて修復しました。 どうりで長いこと投稿がなかったわけだ…
[この投稿を含むスレッドを表示] [この投稿を削除]
[1072] Re:ソースコードの単純な誤植
投稿者:(ぱ)こと管理人
2007/10/08 17:32:28

>以下のような文章が出てきます。 >(下2行はいらないでしょうが、一応載せておきますね。) >----- >i686-apple-darwin8-gcc-4.0.1 (GCC) 4.0.1 (Apple Computer, Inc. build 5367) >Copyright (C) 2005 Free Software Foundation, Inc. >This is free software; see the source for copying conditions. There is NO >warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 情報ありがとうございます。 うちのUbuntu Linuxの gcc (GCC) 4.1.2 20060928 (prerelease) (Ubuntu 4.1.1-13ubuntu5) とやらではこの警告は出ないので、4.x系なら出るのかというとそういうわけでも なさそうですね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1069] Re:ソースコードの単純な誤植
投稿者:cocoatomo
2007/10/08 12:03:36

>gcc --versionで表示されるgccのバージョンは何でしょうか? 以下のような文章が出てきます。 (下2行はいらないでしょうが、一応載せておきますね。) ----- i686-apple-darwin8-gcc-4.0.1 (GCC) 4.0.1 (Apple Computer, Inc. build 5367) Copyright (C) 2005 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -----
[この投稿を含むスレッドを表示] [この投稿を削除]
[1067] Re:ソースコードの単純な誤植
投稿者:(ぱ)こと管理人
2007/10/08 04:08:04

>----- >mycalc.y:64: warning: incompatible implicit declaration of built-in function 'exit' >----- >と警告が出てしまいます。 「of built-in function 'exit'」つまりexit()を組み込み関数とした上で 警告を出してくれるわけですね。 すみません、よろしければ教えていただきたいのですが、 gcc --versionで表示されるgccのバージョンは何でしょうか? うちのMinGW(gcc (GCC) 3.4.2 (mingw-special))ではこの警告は 出ないようです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1065] Re:ソースコードの単純な誤植
投稿者:cocoatomo
2007/10/07 06:42:35

はじめまして。 前回の投稿で挨拶をしていなくて、すみませんでした。 >>8行目 >>"}" → "};" >>"union" の宣言の終わりのセミコロンが無い。 > >これですが、ここはもともとセミコロンは不要ではないでしょうか >(bisonで試したところあってもなくても通りましたが)。 はい、自分のところで試してみたところ、セミコロン無しでも通りました。 エラーメッセージを読み間違えたのだと思います。 >>64行目 >>"exit()" を使用しているのに、"stdlib.h" が include されていない。 > >こちらは修正いたしました。 >gccだとexit()は組み込み関数になっていて、-Wallを付けても、stdlib.hをinclude >していない状態でコンパイルエラーにならなくて… というのは言い訳ですね。 私の環境(MacOSX v10.4.10 Darwin 8.10.1?)で gcc -o mycalc y.tab.c lex.yy.c を実行すると ----- mycalc.y:64: warning: incompatible implicit declaration of built-in function 'exit' ----- と警告が出てしまいます。 なので、一応神経質になって include してみた次第です。 # こういう仔細な状況を書き忘れないようにしようとは思うのですが、 # 忘れてしまいます。すみません。 お早い返信ありがとうございました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1064] Re:ソースコードの単純な誤植
投稿者:(ぱ)こと管理人
2007/10/07 01:26:20

はじめまして。ご報告ありがとうございます。 >8行目 >"}" → "};" >"union" の宣言の終わりのセミコロンが無い。 これですが、ここはもともとセミコロンは不要ではないでしょうか (bisonで試したところあってもなくても通りましたが)。 NUTSHELLの本でも、以下のサンプルでもセミコロンは付いていませんし。 http://www.linux.or.jp/JF/JFdocs/Lex-YACC-HOWTO-6.html#ss6.3 >64行目 >"exit()" を使用しているのに、"stdlib.h" が include されていない。 こちらは修正いたしました。 gccだとexit()は組み込み関数になっていて、-Wallを付けても、stdlib.hをinclude していない状態でコンパイルエラーにならなくて… というのは言い訳ですね。 実は現在公開しているcrowbarやDikamでも同様の問題があり、最近ようやく -ansiオプションを付けました。次バージョンから修正します。 >私は2行目と3行目の間に "#include <stdlib.h>" という行を挿入したのですが、 >これでいいのでしょうか? それでOKです。 ご報告いただきありがとうございました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1063] ソースコードの単純な誤植
投稿者:cocoatomo
2007/10/06 02:25:44

リンクされているページのソースコード"mycalc.y"に誤りがありましたので、報告いたします。 8行目 "}" → "};" "union" の宣言の終わりのセミコロンが無い。 64行目 "exit()" を使用しているのに、"stdlib.h" が include されていない。 私は2行目と3行目の間に "#include <stdlib.h>" という行を挿入したのですが、これでいいのでしょうか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[1062] 管理者により削除されました
2007/10/04 12:46:19

広告なので削除。 管理者削除がたまってきたのでそろそろDBから物理削除します。
[この投稿を含むスレッドを表示]
[1061] 管理者により削除されました
2007/10/04 12:45:20

意味不明の投稿につき削除
[この投稿を含むスレッドを表示]
[1060] 管理者により削除されました
2007/09/24 04:57:51

エロ系SPAMにつき削除
[この投稿を含むスレッドを表示]
[1059] 管理者により削除されました
2007/09/24 04:57:25

エロ系SPAMにつき削除
[この投稿を含むスレッドを表示]
[1058] 管理者により削除されました
2007/09/19 08:08:21

広告なので削除しました
[この投稿を含むスレッドを表示]
[1056] 管理者により削除されました
2007/09/12 23:12:53

エロ系SPAMだったので削除しました。
[この投稿を含むスレッドを表示]
[1055] Re:externと「外部結合」
投稿者:yuya
2007/09/06 15:20:34

> Rationaleを見ても、このへんに関する記述は以下の箇所くらいのようです。 > http://www.lysator.liu.se/c/rat/c1.html#3-1-2-2 rationaleにこんな記述があったのですね。ありがとうございます。 > extern int i3 = 3; > これも不可解ですが、これはcommonモデルの方を引き継いだのでしょうかね。 該当箇所をよく読んでみると、列挙されたモデルの4つ目にinitializionモデルというのがあり、 「定義になるかどうか」を初期化子の有無だけで判断するものがあったようですね。 さらにその後には、 (訳) >規格で採用されたモデルは、strict ref/defモデルとinitializationモデルの特徴を組み合わせたものとなっている。 >(略) >しかし、外部定義として働くのは、「初期化」あるいは「記憶域クラス指定子のない特定の宣言」のいずれでもよい。 >このような混合アプローチが選択されたのは、さまざまな環境と既存の実装に可能な限り広範囲に適応するためである。 とあります。これを読む限り、 extern int i3 = 3; の挙動はinitializationモデルを引き継いだ可能性もありそうです。 同モデルの説明のところにはexternの扱いは明記されていないので、少し話がずれているかもしれませんが。 有用な資料の箇所を指し示してくださってありがとうございました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1054] Re:externと「外部結合」
投稿者:774RR
2007/09/03 15:52:21

C/C++ の予約語に関しては D&E で Stroustrup も書いているんだけど 「新しいキーワードを増やすことは激論を招く」pp.191 C/C++ では同じ予約語を文脈によって異なる意味に使うことで、増やさない選択をした。 違和感の原因はこの辺にありそう。 > 特に「紹介状」は使わせてもらっていいでしょうか。 どーぞご自由に。 <前橋様>すんません、勝手に盛り上がってしまっております。 本来こー言う[俺はこう思う]論は自分で blog 等立てるのが筋なんですが 小心者ですので web は「使う側」に回らせてもらっております。 もう少し掲示板スペースをお貸しください</前橋様>
[この投稿を含むスレッドを表示] [この投稿を削除]
[1053] Re:externと「外部結合」
投稿者:yuya
2007/09/03 14:29:41

▼ > 要するに言語仕様上の extern と、英語の単語 external の不一致に違和感がある > っつーことでっか そうです。すでに決まっちゃったものに文句を言っても仕方ないですが、 「説明するときに名前との関連を前面に出すか、抑えるか」という選択肢は残されています。 そもそも結合は定義サマが決めるのが筋なのであって、 定義でない宣言がいくら結合を声高に主張しても、 「定義との食い違いを処理系に見つけてもらおう」というのでない限り無意味ですよね。 int hoge = 1; static int hoge; でエラーを出してくれるならまだしも、未定義動作ですし。 それならば、「参照に(ほぼ)特化した、結合に関してはオールマイティな」 externのようなキーワードが用意されているのは合理的だと思いますが、 なにもそんな名前じゃなくても良かろう、と思うわけです。 # externは実は外部宣言(external declaration)から来ているのかも、というオチは……。 ▼ > プログラム言語のキーワードをいちいち英語とつき合わせていると違和感ありですな。 > 俺的に一番違和感があるのは const であります。 > const ではなく readonly にしてくれると **俺的には** 解消です。 私もまったく同じように思います。というか、 「文字通りではないことに気付いているかどうか」によって、 理解度が測れてしまうこと自体(Cはこんなのばっかり)、なんて不健全な状況なんだ(^^;) #define INTERN static #define READONLY const ... ▼レベル別教授法はとても参考になりました。 特に「紹介状」は使わせてもらっていいでしょうか。 「エキスパートCプログラミング」には「(定義でない宣言は)税関の申告のようなものだ」とあり、 初めて読んだときは???でしたが。
[この投稿を含むスレッドを表示] [この投稿を削除]
[1052] Re:externと「外部結合」
投稿者:774RR
2007/09/03 11:26:05

ふむー 要するに言語仕様上の extern と、英語の単語 external の不一致に違和感がある っつーことでっか プログラム言語のキーワードをいちいち英語とつき合わせていると違和感ありですな。 俺的に一番違和感があるのは const であります。 const ではなく readonly にしてくれると **俺的には** 解消です。 言語規格書は古い非推奨な書き方してる既存のコードが invalid にならないように 過去との互換性維持のためだけの文言・機能も含んでいるので、そーいうところは 初心者・中級者むけクラスでは一切教えない。教える必要も無い。隠しておくべし。 たとえばいまさら「関数原型宣言にならない関数宣言」など教える必要は一切無い。 「extern があると先行する宣言に従う」はまさにこの黒歴史の部分。初心者に教えるな! # 知っておいて隠しておくのと知らないままでいるのとでは大きく違うのだがね。 extern に関して俺が後輩諸氏に説明するならばレベルに応じ 初心者向け(厳密に宣言を必ず先行させる新しいスタイルのみ教える) ・ヘッダファイル中において変数を宣言する場合には必ず extern を書くべし  →宣言とは他人/自分が [その名前] を使えるようにするものである  →他人の作った未知の関数や変数は使いたくないだろ。だから最低限素性がわからないと困るんだ   だから、ヘッダファイル中には[名前]と「紹介状」を書くべし(=これが宣言) ・他人/自分がその変数を使えるようにするために、定義を1つ .c 中に書くべし  →定義とは [その名前] の変数や関数を作って提供することである  →「紹介状」と実際の人物像が異なると困るだろ、だから紹介状を書く側には責任がある   人間の目でなくコンパイラでチェックできるよう、自作ヘッダは自作ソース中で #include しろ   そーすれば機械が不一致を検出してくれる  →紹介状は複数人で回覧することができる (宣言は複数回あっていい) が、   実際の人物は1人しかいないわけだから定義は1つ。 宣言と定義の簡易解説は必要。詳細解説までは不要。 結合や記憶域期間や可視性、等の詳細については説明不要 (消化不良になるだけ) 中級者向け(旧式の非推奨な書き方してるソースコードには触らせない) ・宣言と定義の詳細解説 ・内部結合と外部結合と無結合の違い  →「原則として」と前置きして extern は外部結合・定義にならない宣言となると解説  (変数宣言に extern があっても定義になりうると話しても混乱を招くだけなので説明しない)  →「原則以外は?」と問われたら上級者向け解説を実施 関数の場合の話を問われたら ・関数宣言と関数定義はソースコード上の記述形式が明確に異なるので区別できるから  extern/static は結合の決定にのみ使われるとフォローし ・static が明記されていない場合は extern が省略されていると解説 (X3010:1993 に準拠) ・これは変数の場合と挙動が異なるぞ、ともフォロー 上級者向け(既存のソースコードのダークサイドまで全部面倒見る人向け) ・言語規格書の章番号+解説 ・相手に興味がありそうで時間もあれば既に書いた俺妄想による Rationale をフォロー
[この投稿を含むスレッドを表示] [この投稿を削除]
[1051] Re:externと「外部結合」
投稿者:yuya
2007/09/02 16:34:38

774RRさん、(ぱ)さん、ありがとうございます。 たくさんコメントをいただいたので、[1045]~[1050]へのリプライは こちらにまとめさせていただきます。 [1048]774RRさん; > ながながと書いたけど結局のところ yuya さんの疑問点は > extern 記憶域指定子はなぜに (6.2.2) のようなヘンな振る舞いをするのか、その根拠やいかに > ということでよろしいのだろうか? [1049](ぱ)さん; >>static int i2 = 2; // 定義,内部結合 >>extern int i2 ; // 内部結合をもつ前の定義を参照する > > この「extern int i2;」の挙動が不可解だということですよね。 > 私にも不可解に見えます。そもそもキーワードの名前が「extern(al)」なのに! 6.2.2のexternの振る舞いが奇妙に映るのは、(ぱ)さんのおっしゃるとおり、 `extern'という、外部結合(external linkage)を想起させる名前によるところが大きいと思います。 いったん名前のことを忘れて、単に 「(翻訳単位内外にかかわらず)どこかで定義されている(かもしれない)変数・関数を参照する」 という機能が主眼だと考えれば、6.2.2の結合の定まり方は、 「可能な限り状況に合わせて結合を決定する」という、ある意味ではきわめて合理的な、 悪く言えば御都合主義的な仕様になっています。 その背景には[1048]・[1050]で774RRさんが書いてくださったような事情があった可能性が高いと思います。 現在の目から見て、初心者に「結局のところexternって何をするんですか?」と聞かれたとき、 最も正しい答えは[1046]でまとめていただいたように規格書の該当箇所を指し示すことだと思いますし、 最終的には本人にそこまで行き着いてもらわないといけないわけですが、 やはり(自分自身の頭を整理するためにも)「何が原則で、何が例外か」という観点で整理したくなり、 できるだけ普遍的な原則・少ない例外で理解できる方法はないだろうか、と思ってしまうわけです。 その過程の中で、歴史的経緯を知ることが原則を抽出する助けになることも多いと思います。 もちろん規格書には「これが原則、これが例外」などということは書かれていませんから、 注意しないと私が陥ったように勝手な行間解釈や俺俺用語を生んでしまうわけですが……。 で、実際にexternに対してそのような整理を試みたとき、ポイントとなる切り口は [1047]でご指摘のとおり「結合は何か」「定義になるかどうか」です。 ここでexternという名前を尊重して、「結合指定」を原則に据えると、 内部結合になるケースを例外と捉え、「定義になるかどうか」は別途論じることになります。 これに対して、「定義にならない」ことを原則に据えると、 (a); 結合は上記のように状況に合わせて定まる。 (b); 何も付けなくても初めから外部結合のブロック外定義になっているもの (関数定義や初期化子つきのブロック外変数定義)だけは、externをつけても定義とみなされる。 extern int hoge = 1; /* 外部結合のブロック外定義 */ と整理することができ、(b)が昔はコンパイルエラーになっていたとなれば、 例外として扱うことへの抵抗が小さくなります。 結局のところ、Cの振る舞いを統一的に理解することなど追求すべきでないのかも知れず、 [1045]774RRさんの > なんか難しく考えすぎなのではないかと思ってきた・・・ が最も正しいような気がしてきました。自覚はあるんですけど(^^;)
[この投稿を含むスレッドを表示] [この投稿を削除]