プリプロセッサという考え方はC言語特有のものですが(多分)、うまく使えば実に強力なツールです。ここではプリプロセッサを使ったテクニックを紹介したいと思います。
とは言え私もあまり知らないので皆さんの投稿をお待ちしております。
#ifndef __FILENAME_H_ #define __FILENAME_H_ <ヘッダファイルの中身> #endif
#if 0 <コメントアウトしたい部分> #endif
プログラムをデバックするときにしばしば変数の内容を printf で出力してみたり、実行状態をログファイルに吐かせたりなどといろんなことをしますよね。でもデバックのたびにこれらを入れたり、コメントアウトしたりを繰り返すのは非常に面倒です。そこですかさず使うのが _DEBUG マクロです。まあ名前は何でもいいのですがこんな感じの名前をよく見かけます。でもってデバック用のコードを
#ifdef _DEBUG <デバック用のコード> #endif
折角なんでどう言うものを埋め込むと便利かいくつか考えてみました。
一番よくやることではないでしょうか。最近はデバッカがとかく強力なのでする必要もなくなりつつありますが、昔はよくやりました(マイコン開発では毎日やってる貧乏な私)。
要するに実行状態をログファイルに吐かせることによって実行状態を追いかけます。関数の呼び出し頻度を調べるとか、メッセージのログを残すとか、リソースの確保、開放をトレースしてリークを見極めるとか、使い方次第で有用な情報を吐き出す機能を追加することが出来ます。
プログラムのモジュール開発が頻繁になってくるとモジュール側に呼び出し側のミスによるエラーを検出する機構をつけたくなります。要するにモジュール呼び出し時のパラメーターチェックなのどが主なのですが、これに引っかかるものはすべてプログラマのミスであるためデバックが完了してしまうとこれらはただの無駄でしかありません。そこでこのようなコードもデバック時のみ組み込みます。簡単なのは ASSERT マクロを作ってしまうことです。
先ほどの続きですが ASSERT マクロというものを作っておくとデバック時に便利です。MFCなどのライブラリでは当たり前のように実装されていますが、これらのライブラリを使わない場合でも簡単に作れますのでガンガン利用しましょう。
DOSやUNIXのようなコンソール環境だと以下のような感じで宣言すればいいでしょう。
#ifdef _DEBUG #define ASSERT(f) \ if ( !(f) ) { \ fprintf(stderr, "Assertion Failed! %s (%d)\n", __FILE__, __LINE__); \ exit(1); \ } #else #define ASSERT(f) ((void)0) #endif
void func(int* pData, int nIndex) { ASSERT(pData); ASSERT(nIndex >= 0 && nIndex < nDataLength); <関数の処理> }