16

標準は、変数がodrで使用されていない場合、変数の定義の数に制限がないことを暗示しているようです(§3.2/3):

すべてのプログラムには、そのプログラムで ODR で使用されるすべての非インライン関数または変数の定義が 1 つだけ含まれている必要があります。診断は必要ありません。

翻訳単位内で変数を複数回定義することはできないと言っています(§3.2/1):

変換単位には、変数、関数、クラス型、列挙型、またはテンプレートの複数の定義が含まれてはなりません。

しかし、プログラム全体で、odr を使用しない変数に対する制限を見つけることができません。では、次のようなものをコンパイルできないのはなぜですか。

// other.cpp
int x;

// main.cpp
int x;
int main() {}

これらのファイルを g++ 4.6.3 でコンパイルおよびリンクすると、multiple definition of 'x'. 正直なところ、私はこれを期待していますが、x(私が知る限り)どこでも使用されていないため、標準がこれをどのように制限しているかわかりません。それとも未定義の動作ですか?

4

4 に答える 4

8

この点で標準に誤りがあることは間違いありません。このケースは、3.2p1 (質問のように、翻訳単位ごとに最大で 1 つの定義) と 3.2p6 (クラス、列挙、インライン関数、およびさまざまなテンプレートが重複した定義を持つ方法を説明する) の間のギャップに陥ると感じています。翻訳単位)。

比較のために、C では、6.9p5 はそれを必要とします (私の強調):

外部定義は、関数 (インライン定義以外) またはオブジェクトの定義でもある外部宣言です。外部リンケージで宣言された識別子が式で使用される場合 (結果が整数定数になるsizeofor演算子のオペランドの一部として以外)、プログラム全体のどこかに、識別子の外部定義が 1 つだけ存在する必要があります。それ以外の場合、 は 1 つしか存在しないものとします_Alignof

于 2012-10-19T17:38:31.057 に答える
1

標準が未使用の変数の定義について何も述べていない場合、複数の変数がある可能性があることを暗示することはできません。

この国際規格が動作の明示的な定義の記述を省略した場合も、未定義の動作が予想される場合があります。

そのため、コンパイルして正常に実行されるか、翻訳中にエラー メッセージが表示されて停止するか、ランタイムがクラッシュする可能性があります。

編集:James McNellisの回答を参照してください。実際には、標準には実際にルールがあります。

于 2012-10-19T16:57:28.440 に答える
0

コンパイルにエラーはありません。エラーはそのリンケージにあります。デフォルトでは、グローバル変数または関数は他のファイルに公開されている(externストレージがある)ため、最後にリンカーがコードをリンクしたい場合、2つの定義が表示されx、そのうちの1つを選択できないためxmain.cppin を使用しない場合other.cpp逆にそれらを静的にします(つまり、それを含むファイルにのみ表示されます)

// other.cpp
static int x;

// main.cpp
static int x;
于 2012-10-19T16:52:48.257 に答える