EXTERNマクロの話

C言語のソースでよく見かけるEXTERNマクロというトリックについてあれこれ。

EXTERNマクロとは

ヘッダファイルで変数宣言に使われる次のようなマクロです。

#undef      EXTERN
#ifdef  _HOGE_
    #define EXTERN  
#else
    #define EXTERN  extern
#endif

EXTERN	int hoge;

くどくど説明は不要と思います。_HOGE_が定義されているソースからincludeすると実体の定義になり、それ以外からincludeすると外部変数宣言になるというトリックです。外部に公開するグローバル変数の宣言に用いられます。

トリックを使うことの是非

原則として、言語の文法に手を加えるかのようなトリッキーなマクロは好ましくありません。ただ、このEXTERNマクロはじゅうぶん広く知られていて、便利なものなので使ってかまわないと個人的には思います。

変種

EXTERNマクロの変種でGLOBALとかPUBLICというのもたまに見かけます。変種といっても、名前が違うだけ。定義も使い方もEXTERNマクロと全く同じです。PUBLICというはC++等のpublicキーワードからの連想なのでしょう。さらには、次のようなPRIVATEマクロが定義されている場合もあります。

#define PRIVATE static

もう、C++で書けよと思います。

関数プロトタイプ宣言で使う?

たまに、関数プロトタイプ宣言にまでこのEXTERNマクロを使う人がいます。控えめに言って、これは無意味です。関数プロトタイプ宣言にexternがあってもなくても同じだからです。もちろん明示的にexternをつけることが間違いだとは言えません。しかしそれならEXTERNマクロなど使わずにふつうにexternと書けばよいのです。わざわざ手間を増やして可読性を落とすようなマクロを使うべきではありません。

externおさらい

externキーワードについて厳密に説明すると長い話になりますし、意外と誤解が横行してるのですが、実用上は以下のように書くことが一般的です。

  1. 外部に公開する変数
    1. ヘッダではexternをつけて宣言
    2. ソースではexternをつけず定義
  2. 外部に公開する関数
    1. ヘッダではexternをつけず(省略して)プロトタイプ宣言
    2. ソースではexternをつけず定義(処理を記述)

1.1と1.2はexternの有無しか違わないほとんど同じ記述なので、EXTERNマクロで一つにまとめると便利なのです。2.1にEXTERNマクロを使っても何のご利益もありません。

結論

C++で書け。