最近、私のプロジェクトで問題が発生しました。通常は gcc-4 でコンパイルしますが、gcc-3 でコンパイルしようとすると、インライン関数の扱いが異なることに気付きました。これを説明するために、簡単な例を作成しました。
main.c:
#include "header.h"
#include <stdio.h>
int main()
{
printf("f() %i\n", f());
return 0;
}
file.c:
#include "header.h"
int some_function()
{
return f();
}
header.h
inline int f()
{
return 2;
}
gcc-3.4.6 でコードをコンパイルすると:
gcc main.c file.c -std=c99 -O2
-O2
リンカー エラー (f の複数定義) が発生します。フラグを削除しても同じです。コンパイラは、インライン化したくない場合は何もインライン化する必要がないことを知っているので、 と の両方の場合、インライン化する代わりに f をオブジェクト ファイルに配置すると仮定したため、main.c
複数file.c
の定義エラーが発生しました。明らかに、f
静的にすることでこれを修正できます。最悪の場合、f
バイナリにいくつかの があります。
しかし、私はこのコードをgcc-4.3.5でコンパイルしようとしました:
gcc main.c file.c -std=c99 -O2
f
そして、すべてが正常に機能したので、どちらの場合も新しい gcc がインライン化さf
れ、バイナリに関数がまったくないと想定しました (gdb でチェックしたところ、私は正しかった)。
ただし、-O2
フラグを削除すると、 への未定義の参照が 2 つ取得されましたint f()
。そして、ここで、何が起こっているのか本当にわかりません。gcc はf
インライン化されると想定していたようで、オブジェクト ファイルに追加しませんでしたが、後で ( がなかったため-O2
) インライン化する代わりにこれらの関数の呼び出しを生成することを決定し、そこからリンカー エラーが発生しました。
さまざまなコンパイラでの問題を恐れずにプロジェクト全体で使用できるように、インラインで必要な単純で小さな関数をどのように定義および宣言すればよいでしょうか。そして、それらすべてを静的にするのは正しいことですか? それとも、gcc-4 が壊れていて、静的でない限り、いくつかの翻訳単位でインライン関数の複数の定義を使用するべきではありませんか?