web-dev-qa-db-ja.com

externインライン関数はどうなりますか?

.hファイルで関数を次のように定義するとどうなりますか

extern int returnaint(void);

関連する.cファイルで次のように定義します

inline int returnaint(void) {
    return 1;
}

ヘッダーを別の.cファイルに含めて、関数を使用しますか?個別にコンパイルし、.cファイルごとにオブジェクトファイルを作成してリンクすると、インライン関数が含まれますか、それともどうなりますか?

コンパイラがinlineを無視できることはわかっていますが、この場合に無視しないとどうなりますか?

15
musicmatze

inline.cファイルの関数定義に追加したのは、余計なことです。

  • .cファイルのコンパイルユニットには、extern宣言(inlineなし)とinline定義があります。したがって、オブジェクトファイル内の関数のシンボルを発行します。

  • 他のすべてのコンパイルユニットはextern宣言のみを参照するため、最終的な実行可能ファイルを他の.oファイルにリンクすれば、問題なく関数を使用できます。

実際、あなたはそれを間違った方法で回避しているだけです。この機能は、.hファイルにinline定義があり、すべての人に表示されるようにするために使用することを目的としています。この関数の定義は、externと同じように、シンボルの宣言としてのみ機能しますが、定義はしません。

次に、1つの.cファイル(コンパイル単位)でのextern宣言により、シンボルがそこで定義されていることが保証されます。

用語は少しわかりにくいですが、inlinedefinitionはシンボルの宣言として機能し、externdeclarationはシンボルの定義として機能します

24
Jens Gustedt

コンパイルされません。 C11(ISO/IEC 9899:2011)§6.7.4から関数指定子(強調を追加):

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

140)インライン定義は、対応する外部定義や他の翻訳単位の他の対応するインライン定義とは異なるため、静的ストレージ期間を持つ対応するすべてのオブジェクトも、各定義で異なります。

他の.cファイルはヘッダーからinline関数の宣言のみを取得しますが、定義は取得しないため、太字フォントのルールに違反します。

編集:

@Jens Gustedtが指摘しているように、私の前の説明は間違っています。OPの質問では、関数がヘッダーファイルで非インラインとして宣言されているためです。

extern int returnaint(void);

だから他の.cファイルはそれを通常の関数のように扱います。

5
Yu Hao

同様の問題が発生し、.cファイルにのみインラインを保持することで、警告の問題が解決しました。スピードアップは、関数定義がある場合とない場合の両方のファイルでも発生しました。 -o3フラグを使用したコンパイル。

0
Vladimir Kazei