C言語におけるマクロと関数 質問する

C言語におけるマクロと関数 質問する

関数を使用するよりもマクロを使用する方がよい場合がよくあります。

関数と比較したマクロの欠点を例を挙げて説明していただけますか?

ベストアンサー1

マクロはテキストの置換に依存しており、型チェックを実行しないため、エラーが発生しやすくなります。たとえば、次のマクロ:

#define square(a) a * a

整数で使用すると正常に動作します:

square(5) --> 5 * 5 --> 25

しかし、式で使用すると非常に奇妙な動作をします:

square(1 + 2) --> 1 + 2 * 1 + 2 --> 1 + 2 + 2 --> 5
square(x++) --> x++ * x++ --> increments x twice

引数を括弧で囲むと役立ちますが、これらの問題を完全に排除することはできません。

マクロに複数のステートメントが含まれている場合、制御フロー構造で問題が発生する可能性があります。

#define swap(x, y) t = x; x = y; y = t;

if (x < y) swap(x, y); -->
if (x < y) t = x; x = y; y = t; --> if (x < y) { t = x; } x = y; y = t;

これを修正するための通常の戦略は、ステートメントを「do { ... } while (0)」ループ内に配置することです。

同じ名前だがセマンティクスが異なるフィールドを含む 2 つの構造体がある場合、同じマクロが両方で機能し、奇妙な結果になる可能性があります。

struct shirt 
{
    int numButtons;
};

struct webpage 
{
    int numButtons;
};

#define num_button_holes(shirt)  ((shirt).numButtons * 4)

struct webpage page;
page.numButtons = 2;
num_button_holes(page) -> 8

最後に、マクロはデバッグが難しく、奇妙な構文エラーや実行時エラーが発生し、理解するには展開する必要があります (例: gcc -E を使用)。これは、次の例のようにデバッガーがマクロをステップ実行できないためです。

#define print(x, y)  printf(x y)  /* accidentally forgot comma */
print("foo %s", "bar") /* prints "foo %sbar" */

インライン関数と定数は、マクロに関するこれらの問題の多くを回避するのに役立ちますが、常に適用できるわけではありません。マクロが意図的にポリモーフィックな動作を指定するために使用される場合、意図しないポリモーフィズムを回避することは困難です。C++には、マクロを使用せずにタイプセーフな方法で複雑なポリモーフィック構造を作成するのに役立つテンプレートなどの機能が多数あります。StroustrupのC++プログラミング言語詳細については。

おすすめ記事