9

簡単な問題:

次のプログラムが与えられた場合:

#include <stdio.h>

inline void addEmUp(int a, int b, int * result)
{
    if (result) {
        *result = a+b;
    }
}

int main(int argc, const char * argv[])
{
    int i;
    addEmUp(1, 2, &i);

    return 0;
}

リンカーエラーが発生します...

Undefined symbols for architecture x86_64:
  _addEmUp", referenced from:
      _main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

わざわざコンパイルする必要はないようです。

私が読んだ内容に基づいて、そうである必要staticはないと思います:
Linker error inline function (これは別のオブジェクトにあり、ゼロではなく2つの定義を扱っているため)

これは関連リンクですが、これは C++ であり、標準 C でヘッダーにコードを配置するのは良い習慣ではないと思います:
インライン関数リンカー エラー

コンパイラ情報:

cc --version
Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.3.0
Thread model: posix

コンパイル例:

# cc main.c 
Undefined symbols for architecture x86_64:
  "_addEmUp", referenced from:
      _main in main-sq3kr4.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocatio
4

3 に答える 3

11

セクション 6.7.4 のパラグラフ 7 は次のように述べています。

内部リンケージを持つ関数はすべてインライン関数にすることができます。外部リンケージを持つ関数の場合、次の制限が適用されます。関数がinline関数指定子で宣言されている場合、同じ翻訳単位でも定義される必要があります。翻訳単位内の関数のすべてのファイル スコープ宣言に、inline関数指定子が含まれていないextern場合、その翻訳単位内の定義はインライン定義です。インライン定義は関数の外部定義を提供せず、別の翻訳単位での外部定義を禁止しません。インライン定義は、翻訳者が同じ翻訳単位内の関数への呼び出しを実装するために使用できる外部定義の代替手段を提供します。関数の呼び出しがインライン定義を使用するか、外部定義を使用するかは指定されていません

ファイルには の外部定義が含まれておらずaddEmUp、コンパイラは の呼び出しで外部定義を使用することを選択しましたmain

外部定義を提供するか、それを として宣言しstatic inlineます。

于 2013-05-24T17:54:08.343 に答える
0

このプログラムは、非公式に「1 つの定義ルール」と呼ばれることがある 6.9/5 が原因で、未定義の動作 (診断は不要) を引き起こします。

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

プログラムは識別子addEmUpを使用しますが、外部定義は提供しません。(すでに述べたように、「インライン定義は関数の外部定義を提供しません」)。

関数呼び出しがどの定義を呼び出すかなどについて話し始める必要はありません。診断を必要とせずに ODR 違反が未定義である理由は、コンパイラーの作成者を簡単にするためです。このコードに診断が必要な場合、コンパイラはインライン最適化を無効にしてパスを実行し、外部定義の存在をチェックする必要がありますが、これは本当に時間の無駄です。

于 2020-08-28T14:22:09.637 に答える