Cでは、そのような小さな計算にマクロを使用する場合、次のように式の各パラメーターを常に括弧で囲む必要があります。
#define AVERAGE_NUMS(min_val, max_val) (((min_val) + (max_val)) / 2)
マクロの引数リスト内のスペースはオプションであるため、「害」はありません。すでに述べたように、開き括弧の前のスペースはマクロの意味を変更します。その後、パラメーターをとらず、その出現箇所を、パラメーター リストにしたいものと「式」の両方に置き換えます。
括弧内の式に引数を入れないと、演算子の優先順位によって式が変わる可能性があるため、奇妙な結果が生じる可能性があります。これは、マクロが単なるテキスト置換規則であり、プログラミング言語 (C) をまったく尊重しないためです。
失敗する小さな例 (これは奇妙な例ですが、「通常の」使用法が失敗するマクロとして作成する関数は他にもあります):
AVERAGE_NUMS(1 << x, y)
マクロ定義を使用すると、これは次のように展開されます
((1 << x + y) / 2) // Operator precedence: 1 << (x + y)
しかし、上記のマクロ定義を使用すると、次のように展開されます。
(((1 << x) + (y)) / 2) // Operator precedence: (1 << x) + y
C++ では、本当に必要でない限り、マクロを使用しないことを強くお勧めします。
型を指定せずに 2 つの数値の平均を計算するためのより良い方法は、テンプレート メソッドを使用することです。
template<typename T>
T average_nums(T min_val, T max_val) {
return (min_val + max_val) / T(2);
}
パフォーマンスが気になる場合は、最新のコンパイラはすべて、このコードをマクロ定義と同じ方法で処理することに注意してください。つまり、コードをインライン化します。これは、関連する関数呼び出しがないことを意味しますが、式avg(a, b)
は に置き換えられ(a + b) / 2
ます。
これとマクロの違いは、マクロはプリコンパイル中に発生する単なるテキスト置換であるため、実際のコンパイル ステップ(a + b) / 2
では、avg(a, b)
.