K.Maebashi's BBS 投稿フォーム
ハンドル名
件名
Link
>別スレッドを立てました。 > >externと「外部結合」については以前から私の悩みの種で、 >現時点で以下のように理解しているのですが、問題がないかどうか、よろしければご意見をお聞かせください。 > >以下、すべてブロック外の話で、「宣言」とは「定義でない宣言」を指すとします。 > >extern宣言は、同一翻訳単位内にすでに定義があれば、その結合に従った宣言となります。 >定義がなければ他の翻訳単位に定義があるだろうと仮定して、 >それに対応する宣言になろうとします(この場合には、状況から外部結合しかあり得ません)。 > >このようにextern宣言の振る舞いを見ると、externは >「近いところから順に定義を探し、状況に合わせて(きわめて自然に)結合が定まる」 >宣言であると考えられます。 >もちろん、実際にはほとんどのケースで外部結合になり、 >内部結合になるのは同一翻訳単位内にstatic定義がある場合だけですが、 >これを「例外」と捉えるよりも、上記のように結合が定まると考えたほうが良いように思います。 > >初期化子のない変数定義・宣言を考えたとき、記憶クラス指定子をつけなければ外部結合の仮定義になりますが、 >これが(他に定義があるために)宣言に成り下がった場合でも、外部結合であることは動きません。 >したがって、 > >static int hoge = 1; /* 定義(内部結合) */ > int hoge; /* 仮定義(外部結合)、ここでは宣言になるが、結合指定が定義と矛盾する */ > >は未定義動作になります。これに対し、2行目にexternをつけた > >static int hoge = 1; /* 定義(内部結合) */ >extern int hoge; /* 宣言(結合は状況に応じる)、ここでは定義に従い内部結合となる */ > >は問題ありません(ソースを比較すると、後者のほうが「問題あり」に見えてしまいますが)。 >これを「結合」という観点から見ると、「絶対に外部結合」だったものが、 >externを付けることで「結合は状況に合わせる」に変わっています。 >ではexternの実際の機能は何かというと、 >「私は定義ではなく、ただの宣言である。定義はほかにある」ことを明示することにあります。 > >[1024]ひげおやじさんの > >> 「別のところにあるのを宣言する」ってのはexternの本質を表していないのですね。 > >において、「別のところ」というのが「翻訳単位外」を指しているならば、確かに誤りです。 >しかし、その「誤りである理由」は、「外部結合が『翻訳単位内も含む』概念だから」ではなく、 >「externが(結合とは無関係に)翻訳単位内外両方に定義を探しに行くから」ではないでしょうか。 > >そもそもリンケージが翻訳単位外に及ぶ(つまり外部結合)、というのと、 >宣言が定義を探しに行く範囲が翻訳単位外に及ぶ(extern宣言)、というのは >分けて考えるべきだと思うのですが、皆様のご意見はいかがでしょうか? > >なお、ブロック外において明らかに定義と分かるもの(関数定義や、初期化子の付いた変数定義)に >externが付いた場合、外部結合になりますね(付けなくても同じですが)。 >この場合はexternが文字通り「外部結合」を意味していると考えられますが、 >ANSI以前はコンパイルエラーになっていたと聞いたことがあります。
spamよけのため、ここに「ほげぴよ」と入力してください。
削除パスワード :
クリック!