デバッグシステムを実行しようとしていますが、機能しないようです。
私が達成したかったのは次のようなものです。
#ifndef DEBUG
#define printd //
#else
#define printd printf
#endif
それを行う方法はありますか?デバッグメッセージがたくさんありますが、やりたくありません。
if (DEBUG)
printf(...)
code
if (DEBUG)
printf(...)
...
いいえ、できません。前処理ディレクティブの処理が開始される前に、コメントがコードから削除されます。このため、マクロにコメントを含めることはできません。
また、後でマクロトリックを使用してコメントを「形成」しようとしても、機能することが保証されていません。コンパイラは、「遅い」コメントをコメントとして認識する必要はありません。
必要なものを実装する最良の方法は、C99で可変引数を持つマクロを使用することです(または、コンパイラー拡張機能を使用することもできます)。
一般的なトリックはこれを行うことです:
_#ifdef DEBUG
#define OUTPUT(x) printf x
#else
#define OUTPUT(x)
#endif
#include <stdio.h>
int main(void)
{
OUTPUT(("%s line %i\n", __FILE__, __LINE__));
return 0;
}
_
このようにして、printf()
のすべての機能を利用できますが、マクロを機能させるには、二重角かっこを我慢する必要があります。
二重括弧のポイントは次のとおりです。マクロ呼び出しであることを示すために1つのセットが必要ですが、C89のマクロに不確定な数の引数を含めることはできません。ただし、引数を独自の角かっこで囲むことにより、単一の引数として解釈されます。 DEBUG
が定義されているときにマクロが展開されると、置換テキストはWord printf
の後に、実際には括弧で囲まれたいくつかの項目であるsingl引数が続きます。角かっこは、printf
関数呼び出しで必要な角かっこととして解釈されるため、すべてうまくいきます。
С99の方法:
#ifdef DEBUG
#define printd(...) printf(__VA_ARGS__)
#else
#define printd(...)
#endif
これはC99を必要としませんが、コンパイラがリリースバージョンで最適化をオンにしていることを前提としています。
#ifdef DEBUG
#define printd printf
#else
#define printd if (1) {} else printf
#endif
すべてのデバッグ呼び出しを関数に入れ、それをprintf_debug
と呼び、DEBUG
をこの関数内に置くことができます。コンパイラは空関数を最適化します。
一部のコンパイラ(MS VS2010を含む)では、これは機能しますが、
#define CMT / ## /
ただし、すべてのコンパイラーの被付与者はありません。
標準的な方法は
#ifndef DEBUG
#define printd(fmt, ...) do { } while(0)
#else
#define printd(fmt, ...) printf(fmt, __VA_ARGS__)
#endif
そうすれば、最後にセミコロンを追加すると、必要な処理が実行されます。操作がないため、コンパイラは「do ... while」をコンパイルします
未テスト:編集:テスト済み、今では自分で使用しています:)
#define DEBUG 1
#define printd(fmt,...) if(DEBUG)printf(fmt, __VA_ARGS__)
DEBUG
を定義するだけでなく、zer0以外の値を指定する必要があります。
付録:std::cout
でもうまく機能します
C++ 17では、このようなものにconstexprを使用するのが好きです
#ifndef NDEBUG
constexpr bool DEBUG = true;
#else
constexpr bool DEBUG = false;
#endif
その後、あなたはすることができます
if constexpr (DEBUG) /* debug code */
注意点は、プリプロセッサマクロとは異なり、範囲が制限されていることです。あるデバッグ条件で別の条件からアクセスできる変数を宣言することも、外部の関数スコープで使用することもできません。
if
を利用できます。例えば、
#ifdef debug
#define printd printf
#else
#define printd if (false) printf
#endif
-O2
のような最適化フラグを設定すると、コンパイラはこれらの到達不能コードを削除します。このメソッドは、std::cout
にも役立ちます。
マッケイが指摘したように、単にprintd
を//
に置き換えようとすると、問題が発生します。代わりに、可変個引数マクロを使用して、printd
を次のように何もしない関数に置き換えることができます。
#ifndef DEBUG
#define printd(...) do_nothing()
#else
#define printd(...) printf(__VA_ARGS__)
#endif
void do_nothing() { ; }
GDBのようなデバッガーを使用することも役立つかもしれませんが、簡単なprintf
で十分な場合もあります。
私はこの構成をよく使用します:
#define DEBUG 1
#if DEBUG
#if PROG1
#define DEBUGSTR(msg...) { printf("P1: "); printf( msg); }
#else
#define DEBUGSTR(msg...) { printf("P2: "); printf( msg); }
#endif
#else
#define DEBUGSTR(msg...) ((void) 0)
#endif
このようにして、どのプログラムがどのエラーメッセージを表示しているかをコンソールで確認できます...また、エラーメッセージを簡単に検索できます...
個人的には、式の一部だけを#definingするのは好きではありません...
完了しました。私はそれをお勧めしません。テストする時間はありませんが、メカニズムは次のようなものです。
#define printd_CAT(x) x ## x
#ifndef DEBUG
#define printd printd_CAT(/)
#else
#define printd printf
#endif
これは、コンパイラがコンパイラ自体で//コメントを処理する場合に機能します(ANSIのように、/ *コメントに2つのパスがあるという保証はありません)。