インライン関数とプリプロセッサ マクロ

プリプロセッサ マクロは、コードに適用される単なる置換パターンです。これらは、コンパイルが開始される前に展開されたものに置き換えられるため、コードのほぼどこでも使用できます。

インライン関数は、本体が呼び出しサイトに直接注入される実際の関数です。関数呼び出しが適切な場合にのみ使用できます。

ここで、関数のようなコンテキストでマクロとインライン関数を使用する限り、次の点に注意してください:

  • マクロはタイプ セーフではなく、構文的に正しいかどうかに関係なく展開できます。コンパイル フェーズでは、マクロ展開の問題に起因するエラーが報告されます。
  • 予期しないコンテキストでマクロが使用され、問題が発生する可能性がある
  • マクロは、他のマクロを展開できるという点でより柔軟ですが、インライン関数は必ずしもこれを行うわけではありません。
  • マクロは、入力式がパターン内のどこにでもコピーされるため、マクロの展開によって副作用が生じる可能性があります。
  • インライン関数は常にインライン化されるとは限りません。一部のコンパイラは、リリース ビルドでのみインライン化を行うか、そうするように特別に構成されている場合にのみ行います。また、インライン化できない場合もあります。
  • インライン関数は変数 (特に静的なもの) にスコープを提供できます。プリプロセッサ マクロはコード ブロック {...} でのみこれを行うことができ、静的変数はまったく同じように動作しません。

まず、プリプロセッサ マクロは、コンパイル前のコードでは「コピー ペースト」にすぎません。したがって、型チェックはありません 、およびいくつかの副作用 表示できます

たとえば、2 つの値を比較する場合:

#define max(a,b) ((a<b)?b:a)

max(a++,b++) を使用すると、副作用が表示されます 例えば ​​(a または b 代わりに、(たとえば)を使用してください

inline int max( int a, int b) { return ((a<b)?b:a); }

インライン関数はコンパイラによって展開されますが、マクロはプリプロセッサによって展開されますが、これは単なるテキストの置換です.したがって、

    <リ>

    型チェックは関数呼び出し中に行われますが、マクロ呼び出し中は型チェックはありません。

    <リ>

    引数や演算順序の再評価により、マクロ展開時に望ましくない結果や非効率が発生する可能性があります。例えば

    #define MAX(a,b) ((a)>(b) ? (a) : (b))
    int i = 5, j = MAX(i++, 0);
    

    int i = 5, j = ((i++)>(0) ? (i++) : (0));
    
    <リ>

    マクロ引数は、マクロ展開の前に評価されません

    #define MUL(a, b) a*b
    int main()
    {
      // The macro is expended as 2 + 3 * 3 + 5, not as 5*8
      printf("%d", MUL(2+3, 3+5));
     return 0;
    }
    // Output: 16`
    
    <リ>

    関数の場合のように、return キーワードをマクロで使用して値を返すことはできません。

    <リ>

    インライン関数はオーバーロードできます

    <リ>

    マクロに渡されたトークンは、トークン貼り付け演算子と呼ばれる演算子 ## を使用して連結できます。

    <リ>

    マクロは通常、コードの再利用に使用されます。インライン関数は、関数呼び出し中の時間オーバーヘッド (余分な時間) を排除するために使用されます (サブルーチンへのジャンプを回避します)。