私は、オブジェクトのようなプリプロセッサマクロをブールフラグとして[〜#〜] c [〜#〜]コードで定期的に使用して、コードのセクションをオンまたはオフにします。
例えば
#define DEBUG_PRINT 1
そしてそれを次のように使用します
#if(DEBUG_PRINT == 1)
printf("%s", "Testing");
#endif
ただし、#define
を含むヘッダーファイルをソースコードに含めるのを忘れると、問題が発生します。マクロが宣言されていないため、プリプロセッサはマクロを0と同じように扱い、#if
ステートメントは実行されません。
ヘッダーファイルのインクルードを忘れると、予期しない、手に負えない動作が発生する可能性があります。
理想的には、マクロが定義されていることと、マクロが特定の値に等しいことを1行で確認できるようにしたいと考えています。定義されていない場合、プリプロセッサはエラー(または警告)をスローします。
私は次の線に沿って何かを探しています:
#if-def-and-true-else-throw-error(DEBUG_PRINT)
...
#endif
#ifdef
と#if
を組み合わせたようなもので、存在しない場合は#error
を使用します。
いくつかの方法を検討しましたが、プリプロセッサディレクティブを#define
ブロック内で使用することはできません。また、私が知る限り、マクロが定義されていない場合にエラー/警告をスローするプリプロセッサオプションはありません。 #if
ステートメント内で使用されます。
これは一般的なケースでは機能しない可能性があります(あなたが求めているものに対する一般的な解決策はないと思います)が、具体的な例として、このコードのシーケンスを変更することを検討できます。
#if(DEBUG_PRINT == 1)
printf("%s", "Testing");
#endif
に:
if (DEBUG_PRINT == 1) {
printf("%s", "Testing");
}
これは冗長ではなくなり、DEBUG_PRINT
が定義されていない場合、または1
と比較できないものとして定義されている場合は、コンパイルに失敗します。
私が知る限り、
#if
ステートメント内でマクロが定義されていない場合にエラー/警告をスローするプリプロセッサオプションはありません。
C標準では動作が正当であると規定されているため、エラーになることはありません。 ISO C99標準のセクション6.10.1/3から:
マクロ展開によるすべての置換と
defined
単項演算子が実行された後、残りのすべての識別子はpp番号0
....に置き換えられます。
ただし、以下のコメントでJim Balterが指摘しているように、一部のコンパイラ(gccなど)はそれについて警告を出すことができます。ただし、認識されないプリプロセッサトークンを0
に置き換える動作は合法であるため(多くの場合は望ましい)、このような警告を有効にすると、かなりの量のノイズが生成されると思います。
あなたが望むことを正確に行う方法はありません。マクロが定義されていない場合にコンパイルエラーを生成する場合は、明示的に行う必要があります。
#if !defined DEBUG_PRINT
#error DEBUG_PRINT is not defined.
#endif
気にするソースファイルごとに。または、マクロを関数のようなマクロに変換し、#if
の使用を回避することもできます。たとえば、デバッグビルドではprintf
呼び出しに展開されますが、非デバッグビルドでは何にも展開されないDEBUG_PRINT
マクロを定義できます。マクロを定義するヘッダーを含めることを怠ったファイルは、コンパイルに失敗します。
編集:
望ましさについては、コードが使用する場所を何度も目にしました。
#if ENABLE_SOME_CODE
...
#endif
の代わりに:
#ifdef ENABLE_SOME_CODE
...
#endif
そのため、#define ENABLE_SOME_CODE 0
はコードを有効にするのではなく無効にします。
ソースファイルで直接DEBUG_PRINTを使用するのではなく、これをヘッダーファイルに入れます。
#if !defined(DEBUG_PRINT)
#error DEBUG_PRINT is not defined
#endif
#if DEBUG_PRINT
#define PrintDebug([args]) [definition]
#else
#define PrintDebug
#endif
PrintDebugを使用するがヘッダーファイルを含まないソースファイルは、コンパイルに失敗します。
DEBUG_PRINTに基づいてコンパイルされるPrintDebugへの呼び出し以外のコードが必要な場合は、#if
ではなくプレーンif
を使用するというMichael Burrの提案を使用することを検討してください(はい、オプティマイザはfalse定数内でコードを生成しませんテスト)。
編集:マクロ引数のように見えるコンマがない限り、上記のPrintDebugを一般化して任意のコードを含めたり除外したりできます。
#if !defined(IF_DEBUG)
#error IF_DEBUG is not defined
#endif
#if IF_DEBUG
#define IfDebug(code) code
#else
#define IfDebug(code)
#endif
次に、あなたは次のようなものを書くことができます
IfDebug(int count1;) // IfDebug(int count1, count2;) won't work
IfDebug(int count2;)
...
IfDebug(count1++; count2++;)
はい、両方を確認できます:
_#if defined DEBUG && DEBUG == 1
# define D(...) printf(__VA_ARGS__)
#else
# define D(...)
#endif
_
この例では、_#define DEBUG 0
_でも1と等しくないため、何も出力されません。
あなたもこれを行うことができます:
_#if defined DEBUG && DEBUG
# define D(...) printf(__VA_ARGS__)
#else
# define D(...)
#endif
_
ここで_#define DEBUG 0
_そしてD(1,2,3)
の場合も何も出力されません
実際の印刷を行うマクロDEBUG_PRINTを作成するだけです。
#define DEBUG_PRINT(n, str) \
\
if(n == 1) \
{ \
printf("%s", str); \
} \
else if(n == 2) \
{ \
do_something_else(); \
} \
\
#endif
#include <stdio.h>
int main()
{
DEBUG_PRINT(1, "testing");
}
マクロが定義されていない場合、シンボルが認識されないため、コンパイラエラーが発生します。
#if 0 // 0/1
#define DEBUG_PRINT printf("%s", "Testing")
#else
#define DEBUG_PRINT printf("%s")
#endif
したがって、「0の場合」は何もせず、「1の場合」は定義されたマクロを実行します。