デバッグ


条件付きコンパイル

プリプロセッサディレクティブは、プログラムの一部を条件によって選択してコンパイルする命令があります
条件付きコンパイルによって、柔軟なコンパイルが可能になります

条件付きコンパイルは、ifステートメント同様に
指定された定数式が真であれば、指定範囲をコンパイルします

#if 定数式

#endif

#ifディレクティブは、#endif までの文の並びをコンパイルします
ただし、この作業はコンパイルより前にされるため、定数は定数以上の意味を持ちません
つまり変数は指定できないということです

定数式の真偽は、ソースコードに直接記述することになります
このコードによって、コンパイル処理の流れを変え、デバッグなどに利用することができます
#include <stdio.h>
#define DEBUG 1

int main() {
        #if DEBUG
                printf("Back To Your True Shape\n");
        #endif
        printf("CLOW CARD");
        return 0;
}
マクロ DEBUG を #if が評価します
DEBUG が真であれば、#endifまでの文をコンパイルします
何度も言うようですが、これは実行時に判断されるのではなく、コンパイル前に処理されます

やはり、プリプロセッサディレクティブにも #if に対応して #else というのがあります
説明不用でしょうが、使用方法はif-elseと同様です
この機能を利用して、開発中にコンパイルするソースと、製品版にコンパイルするソースを分けることができます

#if 定数式

#else

#endif

#endif はひとつしか必要ありません
#else は#ifが偽の時に指定された文をコンパイルします
#include <stdio.h>
#define DEBUG 0

int main() {
        #if DEBUG
                printf("Back To Your True Shape\n");
        #else
                printf("Back To Your False Shape\n");
        #endif
        printf("CLOW CARD");
        return 0;
}
さらに、if-else-ifのような、段階構造(入れ子)の条件分岐にも対応しています
このようなには#elifディレクティブを使用します
多くのプラットフォームでコンパイルされることを想定したソースなど
複雑な条件コンパイルを作成するのに向いています

#if 定数式

#elif 定数式

#elif 定数式
...
#endif

次のプログラムは、#elif を用いて段階的に比較を行う例です
#include <stdio.h>

int main() {
        #if 0
                printf("Kitty on your lap\n");
        #elif 1
                printf("Back To Your True Shape\n");
        #endif
        printf("CLOW CARD");
        return 0;
}
これらの条件コンパイルには、開発者や開発目的
プロジェクトの規模によって様々でしょう

さらに、マクロ名が定義されているか否かでコンパイルを分岐させることもできます
この場合はマクロに関連付けられている文字に作用しないという特徴があります

マクロは、マクロ名だけの定義さえすれば、その内容を省略することができました
マクロ名だけを #define で指定して、関連付ける文字を指定しない状態です
いっけん意味のないこの機能も、マクロの定義で分岐する条件コンパイルを使用することで威力を発揮します

マクロの定義で分岐するのは#ifdefディレクティブです
偽の時に処理する内容は #else を併用することができます

#ifdef マクロ名

#else

#endif

マクロ名には、存在を確認するマクロ名を指定します
指定されたマクロが定義されていなければ偽と判断されます
#include <stdio.h>
#define DEBUG

int main() {
        #ifdef DEBUG
                printf("Back To Your True Shape\n");
        #else
                printf("Kitty on your lap\n");
        #endif
        printf("CLOW CARD");
        return 0;
}
マクロ名 DEBUG は関連付けられる文字列はありません
しかし、そのマクロ名自体は定義されているので #ifdef はコンパイルされます

これとは逆に作用する#ifndefディレクティブがあります
マクロが定義されていなければコンパイルするということです
#include <stdio.h>
#define DEBUG

int main() {
        #ifndef DEBUG
                printf("Back To Your True Shape\n");
        #else
                printf("Kitty on your lap\n");
        #endif
        printf("CLOW CARD");
        return 0;
}
#ifdefディレクティブに対して、偽を出を評価させてテストしたい場合に便利です
このとき、指定しているマクロ名の定義文を削除する必要がありますが
#ifndefならば、nを付け加えるだけで#elseがコンパイルされるように操作できます
#ifdefを使うか、#ifndefを使うかは、状況に合わせて便利なほうを判断してください

#ifdef以外にも、同様の結果を得ることができる方法があります
#ifとdefinedプリプロセッサ演算子を併用します

#if defined マクロ名

definedは、#ifか#elifのみで使用できます
指定されたマクロ名が定義されていれば真とみなされ、そうでなければ偽になります
他人が書いたソースの解読が出きるように、こちらも記憶しておく必要がありますね
#include <stdio.h>
#define DEBUG

int main() {
        #if defined DEBUG
                printf("Back To Your True Shape\n");
        #else
                printf("Kitty on your lap\n");
        #endif
        printf("CLOW CARD");
        return 0;
}
!演算子を使用すると、真偽を反転させることもできます
#include <stdio.h>
#define DEBUG

int main() {
        #if !defined A

                printf("Back To Your True Shape\n");
        #else
                printf("Kitty on your lap\n");
        #endif
        printf("CLOW CARD");
        return 0;
}
マクロ名 A は定義されていませんが、!演算子によって真偽が反転します
その結果 defined は真となり、#ifの指定範囲がコンパイルされます

また、これは完全にデバッグ用なのですが
コンパイル時にあえてエラーを出しコンパイルを中止するディレクティブがあります
コンパイルを中止させるには#errorを使用します

#error メッセージ

メッセージには、エラー時に出力するメッセージを指定します
ダブルクォーテーションは必要ありません
メッセージは、コンパイラのエラー報告と一緒に出力されます
エラー報告はコンパイラによって異なります
#include <stdio.h>

int main() {
        #error Kitty on your lap
        printf("ひざの上の同居人");
        return 0;
}
printf()関数はコンパイルされることはありません
その前の#error命令で、コンパイラはエラーを出力してコンパイルを中止します


#if constant-expression

定数式constant-expressionが真の場合、この後の文の並びがコンパイルされます
文の終末に、必ず#endifを記述します
#ifとその終了を表す #endif は一対一で記述しなくてはなりません

#ifdef identifier

identifierが、定義されたマクロ名ならば真とみなされます
#elseと併用することもできます
終了ディレクティブ #endif を指定する必要があります

#ifndef identifier

identifierが、定義されたマクロ名ならば偽とみなされます
#elseと併用することもできます
終了ディレクティブ #endif を指定する必要があります

#else

#ifや#ifdefにおいて、偽とみなされた場合にコンパイルする文を指定します
ネストした #else、#elif、#endif ディレクティブは直前の #if ディレクティブの一部になります

#elif constant-expression

#ifのネストとして指定します
constant-expressionが真であれば、指定の文をコンパイルします
#elif ディレクティブは #if ディレクティブと #endif ディレクティブの間にいくつでも指定できます

#endif

#ifの終わりを表します

#error token-string

コンパイルを停止してエラーを出力します
このとき、token-stringをエラーメッセージとして出力します

defined 識別子

定数式が定義されていれば真とみなされ、そうでなければ偽とみなされます
defined ディレクティブは、#if および #elif ディレクティブでのみ使えます



前のページへ戻る次のページへ