プリプロセス中に、プログラム内に出現するすべての「マクロ名」がマクロ定義内の文字列に置き換えられます。これを「マクロ置換」または「マクロ置換マクロ拡張」と呼びます。 。マクロの定義は、ソースプログラム上のマクロ定義コマンドによって完了します。マクロの置換はプリプロセッサによって自動的に行われます。文字列が式の場合、それを関数マクロ定義と呼びます。
次の 2 行のコードを例として説明を拡張してみましょう。
関数マクロ定義: #define MAX(a,b) ((a)>( b)? (a):(b))
通常の関数: MAX(a,b) { return a>b?a:b;}
( 1) 関数マクロで定義されたパラメータには型がありません。プリプロセッサは形式的な置換のみを担当し、パラメータの型チェックは実行しません。そのため、パラメータを渡すときは特に注意してください。
(2) 関数マクロを定義するときは、形式、特に括弧に注意してください。
上記のマクロ定義関数を #define MAX(a,b) (a>b?a:b) として記述し、内括弧を省略すると、後の演算子の優先順位により実行結果が正しくなくなります。マクロ展開; 上記のマクロ定義関数で外側の括弧が省略され、マクロ定義が MAX(a,b) の場合、マクロ展開は (a)>(b)?(a):(b) となり、演算は優先順位も間違っています。
(3) 関数の引数が式の場合、通常の関数呼び出しと関数マクロ定義では置換処理が異なります。
通常の関数が呼び出されるとき、実パラメータ式の値が最初に取得され、次に仮パラメータに渡されます。実パラメータ式に副作用がある場合、これらの副作用は 1 回だけ発生します。たとえば、MAX(a, b) の場合、MAX が通常の関数の場合、a と b は 1 回だけ増加します。ただし、MAX 関数マクロを定義した場合は、k = (( a)>( b)?( a):( b)) と展開する必要があり、a と b は必ずしも 1 回や 2 回増加するわけではありません。したがって、パラメータが式の場合は、関数マクロ定義を置き換えるときに注意する必要があります。
(4) 実関数を呼び出すコードと関数マクロ定義を呼び出すコードでは、コンパイルによって生成される命令が異なります。
MAX が通常の関数の場合、その関数本体 return a > b ? a : b; は命令を生成するためにコンパイルされる必要があります。コード内に表示される各呼び出しも、パラメーターを渡す命令を生成するためにコンパイルされる必要がありますそして呼び出し指示。 MAX が関数型マクロ定義である場合、命令を生成するためにマクロ定義自体をコンパイルする必要はありませんが、コード内に出現する呼び出しごとにコンパイルによって生成される命令は、単なるいくつかのパラメーターではなく、関数本体に相当します。パッシング命令とコール命令。そのため、関数マクロ定義を使用したコンパイルで生成されるターゲットファイルは大きくなります。
利点:
まず第一に、関数呼び出しは追加のオーバーヘッドをもたらします。スタック領域を開き、戻りアドレスを記録し、仮パラメータをスタックにプッシュし、関数を解放する必要があります。関数から戻るときにスタックが発生します。このオーバーヘッドによりコードの効率が低下するため、マクロ定義を使用する方がコード サイズと速度の点で関数よりも優れています。
第 2 に、関数のパラメーターは特定の型として宣言する必要があります。 , そのため、適切な型の式で使用する場合のみ、2 つの浮動小数点型のサイズを比較したい場合は、浮動小数点型専用の比較関数を作成する必要がありますが、上記のマクロ定義は逆に使用できます。整数、long 整数、単一浮動小数点型、二重浮動小数点型、および「<」演算子を使用して値を比較できるその他の型の場合、つまり、マクロは型とは何の関係もありません。
以上がマクロ定義機能の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。