「それは何をしますか?」と答える代わりに、「どうすれば自分のやりたいことをさせることができるか?」と答えています。インライン化には 5 種類あり、すべて GNU C89、標準 C99、および C++ で使用できます。MSVC にはそれらのいくつかがあります (MSVC コードをテストしていないことに注意してください)。
アドレスが取得されない限り、常にインライン
任意の宣言に追加__attribute__((always_inline))
し、以下のいずれかのケースを使用して、そのアドレスが取得される可能性を処理します。
セマンティクスが必要でない限り (たとえば、特定の方法でアセンブリに影響を与える、または を使用するalloca
)、おそらくこれを使用しないでください。コンパイラは通常、それが価値があるかどうかをあなたよりもよく知っています。
MSVC には__forceinline
ほとんど同じように見えますが、他のコンパイラが適切に管理するかなりの数の一般的な状況 (最適化がオフの場合など) でインライン展開を拒否しているようです。
インライン化して弱いシンボルを発行する (C++ のように、別名「動作させるだけ」)
__attribute__((weak))
void foo(void);
inline void foo(void) { ... }
これにより、同じコードのコピーがたくさん残り、リンカが任意に 1 つを選択することに注意してください。
MSVC は、C モードで正確に同等のものを持っているようには見えませんが、似たようなものがいくつかあります。__declspec(selectany)
データのみについて話しているように見えるので、関数には当てはまらないのでしょうか? 弱いエイリアスのリンカー サポートもありますが、ここでは機能しますか?
インライン、ただしシンボルを発行しない (外部参照を残す)
__attribute__((gnu_inline))
extern inline void foo(void) { ... }
MSVC の__declspec(dllimport)
は、実際の定義 (それ以外の場合は異常) と組み合わされて、おそらくこれを行います。
常に発行する (1 つの TU に対して、上記を解決するため)
ヒント付きバージョンは、C++ では弱いシンボルを出力しますが、C のいずれかの方言では強いシンボルを出力します。
void foo(void);
inline void foo(void) { ... }
または、両方の言語で強力なシンボルを出力するヒントなしで実行できます。
void foo(void) { ... }
一般に、定義を提供するときに TU がどの言語であるかを知っているので、インライン展開はおそらくあまり必要ありません。
MSVC__declspec(dllexport)
はおそらくこれを行います。
すべてのTUでインライン化して発行する
static inline void foo(void) { ... }
1 つを除くこれらすべてについて、上記の宣言static
を追加できます。これは、クリーンなヘッダーを作成し、インライン定義を含む別のファイルをvoid foo(void)
作成するという「ベスト プラクティス」に役立ちます。#include
次に、C スタイルのインラインを使用している場合#define
は、1 つの専用 TU でいくつかのマクロを異なる方法で実行して、アウト オブ ライン定義を提供します。
extern "C"
ヘッダーが C と C++ の両方から使用される可能性があるかどうかを忘れないでください。
関連するものもいくつかあります。
決してインライン化しない
__attribute__((noinline))
関数の任意の宣言に追加します。
MSVC にはあり__declspec(noinline)
ますが、メンバー関数でのみ機能することが文書化されています。ただし、インライン化を妨げる可能性のある「セキュリティ属性」についての言及を見たことがありますか?
可能であれば、他の関数をこれにインライン化するよう強制します。
__attribute__((flatten))
関数の任意の宣言に追加します。
noinline
コンパイル時に定義がわからない関数と同様に、これよりも強力であることに注意してください。
MSVC には同等のものはないようです。[[msvc::forceinline_calls]]
(ステートメントまたはブロックに適用された)の単一の言及を見たことがありますが、再帰的ではありません。