ぴぐノート

Good code is its own best documentation.

C/C++ プログラミング言語

C++のプリプロセッサの復習をしよう その2 【#defineの活用】

投稿日:

前回に引き続き、C++のプリプロセッサの復習です。
前回は#includeと#defineについて記事にしましたが、【まとめ】にも記載の通り、#defineと関連するプリプロセッサは多くあります。

今回は「#ifdef (#if defined)」「#ifndef (#if ! defined)」「#undef」について記事にしようと思います。
実際の開発でもデバッグなどで活用の幅が広いので、普段から使い方に慣れておくと、人のソースを読み込む際に役立ちます。

前回の記事はちょっと雑すぎたので、まずプリプロセッサディレクティブの一覧を示します。

プリプロセッサ・ディレクティブ

#○○のような形式で記述する命令語をプリプロセッサ・ディレクティブといいます。

プリプロセッサ・ディレクティブは、cファイルやcppファイルをコンパイラに渡す前に処理を実行するため、関数などのオーバーヘッドが発生せず有用に使うことができればかなり効果的に動きます。

全部で14種類あり、それぞれの簡単な説明を下記に示します。

#define 識別子とトークン文字列の関連付けを行い、以降コード中に識別子が見つかるたびに指定したトークン文字列と置換を行う。
#error コンパイル時にユーザー指定のエラーメッセージを出力し、コンパイルを終了する。
#import タイプライブラリーの組み込みを行う。
#undef #defineで作成した識別子を削除します。
#elif #else ifの略。#ifと#else、もしくは#ifと#endifの間に記述可能。
#if 整数定数、文字定数、演算子を記述でき、条件付きコンパイルに使用します。
#include ヘッダーファイルなどのインクルードファイルを組み込みます。
#using

/clrでコンパイルされたプログラムにメタデータをインポートします。

#else  #if/#elifと#else、もしくは#if/#elifと#endifの間に記述可能。
#ifdef  #defineで定義されていればTRUEとなるディレクティブです。
#line  コンパイラが管理する行番号およびファイル名を変更します。
#endif  #ifと対になるディレクティブ。#ifの終わりを示す。
#ifndef  #defineで定義されていなければTRUEとなるディレクティブです。
#pragma

プラグマ ディレクティブは、コンピューター固有またはオペレーティング システム固有のコンパイラ機能を指定します。
キーワードにより、マクロ定義内のプラグマ ディレクティブをコーディングできます。

#define / #ifdef / #ifndef

#defineディレクティブは「識別子とトークン文字列の関連付けをしたり、マクロを作成できる。」ということは前回お話ししました。

上記のように記述すれば、以降ソースコード内に「DEBUG」を見つけると「1」に置換します。

#ifdef

#ifdefと#ifndefは、「識別子が#defineによって定義されているか」を判定します。
よく見るコードでは以下のようなものです。

このようにデバッグ中は識別子「DEBUG」を定義しておき、確認用のメッセージなどをいれることでデバッグがしやすくなります。
リリースの際は「#define DEBUG 1」を削除すれば、コンパイラが「#ifdef DEBUG ~ #endif」を無視してくれるので余分なコードが生成されることもありません。

#ifndef

既になんとなく分かっている方も多いかもしれませんが、#ifndefディレクティブは「DEBUGが定義されていなければ~」という判定を行います。

新しくコードを作成する場合は#ifを使おう

この記事を作成するためにMSDNを見ていると、#ifdefや#ifndefは非推奨とまではいかなくとも、#if, #elif, #endifを使用するようにされていました。

現在は過去のC++との互換性維持のために残されているだけとなっているようですね。
新しくコードを作る際に、同様の動作をさせたい場合は以下のように作成するべきです。

まとめ

MSDNでは#ifとdefined(identifier)を使用するようにと記載されていますが、実際にはまだまだ#ifdef/#ifndefは使われていますし、見る機会もかなり多いと思います。

if文もそうですが入れ子などが複雑になってくると、かなり分かりづらくなりますので急に慌てないようにしっかり理解していなければいけませんね

スポンサーリンク

スポンサーリンク

-C/C++, プログラミング言語

執筆者:

関連記事

【Boost】boost::property_treeの例外処理を考えよう!

ライブラリなどを使用していると、「使い方は大体分かった!使ってみよう!」とすると微妙にはまってしまうことがあります。 前回・前々回でお話しした文字コードもその一つですが今回は例外処理について考えてみま …

C++でインターフェイスを作成しよう。

私事ですが今後業務ではC++を使用することになりそうです。 今まではウェブ関連の業務であったり、ちょっとしたテスト程度だったのでJavaを中心に使っていたため、C++の文法など少し忘れ気味です&#82 …

【OpenCV】MFCのピクチャーコントロールに描画しよう!

前回、OpenCVを使って画像の回転や二値化などを行って動作確認をしました。 今回はMFCでダイアログベースのアプリケーションを作成し、ピクチャーコントロールにOpenCVで読み込んだ画像を表示させて …

【C++11】後処理が必要なリソースはスマートポインタを使おう

オープンソースのライブラリのソースコードを呼んでいるとC++11で追加されたunique_ptrを使用しているところもちらほらと見られるようになってきています。 MFCなどを利用していれば動的確保した …

【OpenCV】OpenCVをビルドして画像処理をしてみよう!

今日はOpenCVを使って画像表示をしてみたいと思います。 ツールやアプリケーションを作る場合、多かれ少なかれ画像処理は必要になってくるのではないでしょうか。 また画像処理関係ではまると泥沼化する場合 …