web-dev-qa-db-ja.com

マクロが定義されており、同時に特定の値に等しいことを確認する方法はありますか

私は、オブジェクトのようなプリプロセッサマクロをブールフラグとして[〜#〜] 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ステートメント内で使用されます。

18
gbmhunter

これは一般的なケースでは機能しない可能性があります(あなたが求めているものに対する一般的な解決策はないと思います)が、具体的な例として、このコードのシーケンスを変更することを検討できます。

#if(DEBUG_PRINT == 1)
    printf("%s", "Testing");
#endif

に:

if (DEBUG_PRINT == 1) {
    printf("%s", "Testing");
}

これは冗長ではなくなり、DEBUG_PRINTが定義されていない場合、または1と比較できないものとして定義されている場合は、コンパイルに失敗します。

10
Michael Burr

私が知る限り、#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はコードを有効にするのではなく無効にします。

11
jamesdlin

ソースファイルで直接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++;)
8
Jim Balter

はい、両方を確認できます:

_#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)の場合も何も出力されません

[〜#〜] doc [〜#〜]

2
Eugen Konkov

実際の印刷を行うマクロ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");
}

マクロが定義されていない場合、シンボルが認識されないため、コンパイラエラーが発生します。

0
Lundin
#if 0 // 0/1
#define DEBUG_PRINT printf("%s", "Testing")
#else
#define DEBUG_PRINT printf("%s")
#endif

したがって、「0の場合」は何もせず、「1の場合」は定義されたマクロを実行します。

0
Sam Keith