#defineを使うのは代替手段が無い場合のみに抑えたい

注意: この記事は1年以上前に掲載されたものです。情報が古い場合がありますのでお気を付け下さい。

C言語及びその派生のC++、Objective-Cでよく使われているマクロとして、#defineがある。これは、特定の文字を別の文字に置き換えるというマクロで、C言語を中心に多重インクルードの防止や定数、インライン展開する関数などにマクロが用いられていた。

個人的にはインクルードガード目的以外では以下の理由で使うのは好ましくないと考えている

まず、型安全ではないことである。基本的に#defineはソースコード内のコードの文字列を置き換えるだけなので、その定義の型を指定できないからである。その点ではconst修飾子付きの変数(定数)やenum、インライン関数などでは単純な文字列の置き換えではないため、型を指定することができ、その点では比較的バグを防ぎやすいと言える。定数の定義では基本的にマクロではなく、const修飾子による定数あるいはenumを使用したい。

最も、C言語では型にとらわれない関数を定義できない ((例えばint型やdouble型用の変数を別途定義しなければならない)) ため、その点ではマクロによるインライン展開は不可欠となっている。例えば、最大値を取り出す場合は以下のようになるだろう。

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

これも、現在のC++ではテンプレートを使用すれば不要である。C++であれば、以下のように書ける。

template<typename T> max(T a, T b)
{
    return a < b ? a : b;
}

この点をふまえると、通常の変数(定数)や関数のように使える方がコーディング上好ましいと言える。

なお、多重インクルードについては、Objective-Cでは#importを使う限りはインクルードガードなしでも多重インクルード問題は発生しないこと、マイクロソフト系の処理系を中心に#pragma onceを使用するという手段があるものの、#pragma onceはデファクトスタンダードと化してはいるものの標準仕様ではないため、使用するのはあまり好ましくない。

マクロを使おうとする時は、それに代わる手段があるかどうか考えて、無い時に限って使うようにしたい。

タイトルとURLをコピーしました