web-dev-qa-db-ja.com

Cでコメントを#defineできますか?

デバッグシステムを実行しようとしていますが、機能しないようです。

私が達成したかったのは次のようなものです。

#ifndef DEBUG
    #define printd //
#else
    #define printd printf
#endif

それを行う方法はありますか?デバッグメッセージがたくさんありますが、やりたくありません。

if (DEBUG)
    printf(...)

code

if (DEBUG)
    printf(...)

...
28
Ben B.

いいえ、できません。前処理ディレクティブの処理が開始される前に、コメントがコードから削除されます。このため、マクロにコメントを含めることはできません。

また、後でマクロトリックを使用してコメントを「形成」しようとしても、機能することが保証されていません。コンパイラは、「遅い」コメントをコメントとして認識する必要はありません。

必要なものを実装する最良の方法は、C99で可変引数を持つマクロを使用することです(または、コンパイラー拡張機能を使用することもできます)。

29
AnT

一般的なトリックはこれを行うことです:

_#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関数呼び出しで必要な角かっこととして解釈されるため、すべてうまくいきます。

20
Tim

С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
18
Xeor

すべてのデバッグ呼び出しを関数に入れ、それをprintf_debugと呼び、DEBUGをこの関数内に置くことができます。コンパイラは空関数を最適化します。

8
slurdge

一部のコンパイラ(MS VS2010を含む)では、これは機能しますが、

#define CMT / ## /

ただし、すべてのコンパイラーの被付与者はありません。

5
Igor Barbarian

標準的な方法は

#ifndef DEBUG
    #define printd(fmt, ...)  do { } while(0)
#else
    #define printd(fmt, ...) printf(fmt, __VA_ARGS__)
#endif

そうすれば、最後にセミコロンを追加すると、必要な処理が実行されます。操作がないため、コンパイラは「do ... while」をコンパイルします

2
Dipstick

未テスト:編集:テスト済み、今では自分で使用しています:)

#define DEBUG 1
#define printd(fmt,...) if(DEBUG)printf(fmt, __VA_ARGS__)

DEBUGを定義するだけでなく、zer0以外の値を指定する必要があります。

付録:std::coutでもうまく機能します

1
drahnr

C++ 17では、このようなものにconstexprを使用するのが好きです

#ifndef NDEBUG
constexpr bool DEBUG = true;
#else
constexpr bool DEBUG = false;
#endif

その後、あなたはすることができます

if constexpr (DEBUG) /* debug code */

注意点は、プリプロセッサマクロとは異なり、範囲が制限されていることです。あるデバッグ条件で別の条件からアクセスできる変数を宣言することも、外部の関数スコープで使用することもできません。

1
Jesse Maurais

ifを利用できます。例えば、

#ifdef debug
    #define printd printf
#else 
    #define printd if (false) printf
#endif

-O2のような最適化フラグを設定すると、コンパイラはこれらの到達不能コードを削除します。このメソッドは、std::coutにも役立ちます。

0
Ricky Hsu

マッケイが指摘したように、単にprintd//に置き換えようとすると、問題が発生します。代わりに、可変個引数マクロを使用して、printdを次のように何もしない関数に置き換えることができます。

#ifndef DEBUG
    #define printd(...) do_nothing()
#else
    #define printd(...) printf(__VA_ARGS__)
#endif

void do_nothing() { ; }

GDBのようなデバッガーを使用することも役立つかもしれませんが、簡単なprintfで十分な場合もあります。

0
Swiss

私はこの構成をよく使用します:

#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するのは好きではありません...

0
Brian Postow

完了しました。私はそれをお勧めしません。テストする時間はありませんが、メカニズムは次のようなものです。

 #define printd_CAT(x) x ## x
 #ifndef DEBUG
    #define printd printd_CAT(/)
 #else
    #define printd printf
 #endif

これは、コンパイラがコンパイラ自体で//コメントを処理する場合に機能します(ANSIのように、/ *コメントに2つのパスがあるという保証はありません)。

0
Joshua