25

重複の可能性:
インライン関数とプリプロセッサ マクロ

インライン関数とマクロ関数の違いが知りたいです。

1) インライン関数はマクロ関数と同じですか?

2) 両方とも呼び出されていないことはわかっていますが、コンパイル段階でそのコードに置き換えられます。ではありません?

3) 違いがあれば教えてください。

4

4 に答える 4

38

インラインは関数の呼び出しを関数の本体に置き換えますが、インラインは無視できるコンパイラへの要求にすぎません (コンパイラにいくつかのフラグを渡してインラインを強制したり、gcc でalways_inline属性を使用したりすることもできます)。

一方、マクロはコンパイル前にプリプロセッサによって展開されるため、テキスト置換と同じように、マクロは型チェックされず、インライン関数は型チェックされます。ウィキに比較があります。

完全を期すために、たとえば gcc を使用して、マクロである種のタイプ セーフを維持することもできます。__typeof__たとえば、次のコードはほぼ同一のコードを生成し、間違ったタイプで使用すると警告が発生します。

#define max(a,b) \
  ({ __typeof__ (a) _a = (a); \
      __typeof__ (b) _b = (b); \
    _a > _b ? _a : _b; })

__attribute__((always_inline)) int max(int a, int b) {
   return (a > b ? a : b);
}

注: 型のないマクロが必要な場合もあります。たとえば、uthashがマクロを使用して、キャストに頼らずに C 構造体をハッシュ可能にする方法を見てください。

于 2012-11-14T08:36:10.847 に答える
31

1) いいえ。

2) C のマクロは、コンパイラがソース コードを処理する前に展開される単なるテキストです。inline キーワードは、コール スタックを設定しなくても関数をインラインに配置できるというコンパイラへのヒントとして使用されます。

たとえば、次の 2 つのコード スニペット (最初にマクロ、次にインライン関数) があるとします。

#define MAX(x,y)     (x > y ? x : y)

inline int max(int x, int y) { return x > y ? x : y; }

プリプロセッサがコード内で次の呼び出しを検出した場合:

int highest = MAX (var_1, var_2);

それはそれを

int highest = (var_1 > var_2 ? var_1 : var_2);

上記は、コンパイラがコンパイル プロセス中に最終的に取得するものであるため、MAX(x,y) で定義されたスニペットはMAX(var_1, var_2)の代わりになります。コンパイラが関数呼び出しを見つけたとき

int highest = max (var_1, var_2);

次に、関数「max」が呼び出されます。コンパイラは自由に「インライン」ヒントを無視し、関数のコードを単純にその場所に配置するのではなく、通常の呼び出しスタックを経由して関数を呼び出すことができるため、通常の方法で呼び出されると想定する必要があります。遭遇した。

マクロに関する最後の警告: これはすべてテキストの置換であり、コードの置換ではないため、次のような場合:

int highest = MAX (v1++, v2++);

プリプロセッサはそれを次のように展開します。

int highest = (v1++ > v2++ ? v1++ : v2++);

これはおそらく意図したものではありません。

于 2012-11-14T09:04:29.453 に答える
6

マクロは、(実際のコンパイルの前に) プリプロセッサによって置換される宣言です。関数ではありません。実際のコンパイル段階が始まる前に、マクロはとうの昔になくなっており、残っているのはそれらの展開 (何もない展開を含む) だけです。

実際、インライン関数は、スコープ規則、変数宣言、論理構造 (ループなど) などを備えた言語準拠の関数です。インライン関数は、マクロのようにコンパイル前の段階で展開されません。これらは通常のコードと同じようにコンパイルされますが、必要に応じてコンパイルされたコードに (適切な用語がないため) 挿入され、最適化されます。

于 2012-11-14T08:40:47.203 に答える
1

いいえinlineは定義と同じではありませんmacro。マクロは前処理されますが、インラインは関数の本体全体を呼び出される場所に配置するためのコンパイラへの指示にすぎません。

関数定義の前に inline キーワードを置くことは単なる指示または要求であり、コンパイラーはその関数をインラインにするか、通常のままにするかを自由に選択できます

マクロ置換: preprocessing phase(つまり、コンパイル前)

test.c-- Linux での入力ファイルの結果ファイルtest.i

インライン置換:compilation phase

于 2012-11-14T08:38:33.040 に答える