web-dev-qa-db-ja.com

コンパイラーにプログラム内の一部の行を無視させる

10,000行のC++コードがあるとします。このコードの200行はテスト用です(たとえば、プログラムをチェックしてエラーメッセージを表示します)。

C++でコードの一部の行を無視または検討する方法はありますか(おそらく プリプロセッサ キーワードを使用)?

48
user1436187

短い答え:

macrosおよび#ifdefチェックを使用します。例えば:

#ifdef MY_CONTROL_MACRO
...
#endif

このスコープ内のコードは、MY_CONTROL_MACROマクロを既に定義している場合にのみコンパイルされます。


その他のもの:

  1. このようなマクロを定義するには、次のことができます

    • #define MY_CONTROL_MACROをコードに追加します。または、
    • VSの場合、MY_CONTROL_MACROProject > Properties > C/C++ > Preprocessor > Preprocessor Definitionsに追加します。または、
    • GCCの場合、オプション-DMY_CONTROL_MACROを使用してコードをコンパイルします。
  2. 詳しくは here をご覧ください。

    このブロックは条件付きグループと呼ばれます。 MACROが定義されている場合にのみ、プリプロセッサの出力に制御テキストが含まれます。 MACROが定義されていれば条件は成功し、定義されていなければ失敗すると言います。

    条件内の制御テキストには、前処理ディレクティブを含めることができます。これらは、条件が成功した場合にのみ実行されます。条件グループは他の条件グループ内にネストできますが、完全にネストする必要があります。つまり、「#endif」は常に最も近い「#ifdef」(または「#ifndef」、「#if」)と一致します。また、あるファイルで条件付きグループを開始し、別のファイルで終了することはできません。

  3. 高度なifdef-else-endifスタイルも使用できます。

    #ifdef MY_CONTROL_MACRO
        ... // this part will be valid if MY_CONTROL_MACRO is defined
    #else
        ... // this part will be valid if MY_CONTROL_MACRO is NOT defined
    #endif
    
78
herohuyongtao

コードを「#ifdef ...#endif」で囲み、コンパイラオプションを使用してフラグを設定します。

#ifdef MYTEST_ONLY_FUNCTIONALITY_ENABLED
...
#endif

その後、コンパイラオプションを使用してこのコードを含めることができます。たとえば、GCCの場合:

-DMYTEST_ONLY_FUNCTIONALITY_ENABLED

正直なところ、このアプローチは大規模なプロジェクトでは一般的にあまりメンテナンスが難しいと思います。可能であれば、テスト専用コードを完全に独立したライブラリに移動して(この条件ロジックなしで)単純にリンクする方が一般的です非テストバイナリではなく、テストバイナリにコードを記述します。また、デバッグモードと非デバッグモードの両方で他の各ライブラリをコンパイルする必要がなくなります。

13

これは何 #ifdef

あなたが置く

#ifdef TESTS
... test code ...
#endif

そして、コンパイラオプションに渡して、テストパーツをコンパイルするかどうかを決定できます。たとえば、g ++では

g++ -DTESTS ...
6
6502

プリプロセッサガードの使用は、間違いなく最も柔軟で一般的なアプローチです。ただし、可能であれば、ifステートメントを使用することをお勧めします。たとえば、代わりに

void example(int a){
   int some_local;
   ...
   #ifdef _DEBUG
   std::cout << "In function " << __FUNCTION__ << "(" << a <<")" << std::endl;
   #endif
   ....
}

ENABLE_DEBUGが0または非ゼロに定義されていると仮定すると、私は

void example(int a){
   int some_local;

   ...
   if(ENABLE_DEBUG) std::cout << "In function " << __FUNCTION__ << "(" << a <<")" << std::endl;
   ...
}

ENABLE_DEBUGは定数であるため、ENABLE_DEBUGが0の場合、コンパイラは保護するステートメントのコードを生成しません。では、なぜ#ifdefの代わりにこのメソッドを使用するのですか?

  1. コード全体に多数の個別のデバッグステートメントが分散している場合、読みやすくすることができます。
  2. さらに重要なことは、コードが生成されない場合でも、コードは常に構文エラーのために処理されます。これは、デバッグコードが頻繁に有効になっていない場合に非常に役立ちます。変数が変更された場合(たとえば、引数aの名前が変更された場合の上記の例)、変更を行う人は、デバッグステートメントも更新する必要があることを知っています。 #ifdefsが使用されている場合、誰かがデバッグコードを有効にする必要があるまでビット腐敗を隠してから、コードを修正しようとする必要があります。

明らかに、このアプローチはメソッド/関数本体内のデバッグステートメントに対してのみ機能します。

4
TheDuke

existing規約に従って、NDEBUGマクロを使用します。すべての一般的なコンパイラは、releaseビルドに対してこのマクロを定義し、debugビルドに対しては定義しません。

このマクロは元々assert(3)の出力を制御するために存在し、 POSIX標準では および少なくともC89以降、そのように定義されています。

#ifndefを使用してテストを元に戻す必要があることに注意してください。

例:

#ifndef NDEBUG
    /* Debugging code */
    std::cerr << "So far we have seen " << unicorns << " unicorns" << std::endl;
#endif

追伸gcc/g++を使用すると、-gをコマンドラインに追加してデバッグビルドを実行できます。

3
Michael Hampton

プリプロセッサの#defineと#ifを使用します

コンパイラに応じて、デフォルトでいくつかの変数、つまりNDEBUG(非デバッグ用)またはDEBUGを使用できるようにする必要があります

コードで変数を自分で定義できます

#define MY_VARIABLE

次のように使用します

#ifdef MY_VARIABLE
  //code that compiles only if MY_VARIABLE is defined
  printf("test output here");
#else
  //code that compiles only if MY_VARIABLE is NOT defined
  printf("MY_VARIABLE is not defined");
#endif

詳細については、オンラインで検索してください

#define, #if, #ifdef, #ifndef
2
user3218782

テストコードを囲む#ifdef DEBUG

#if DEBUG
   ....
#endif
2

進む方法は、コンパイラに渡されるか、ヘッダー「config.h」から取得されるdefineでプリプロセッサディレクティブを使用することです。

#if defined(DEBUG) // or #ifdef DEBUG
    // Debug code
#endif

ソースコードのどこでも使用しないようにするには:

#if defined(DEBUG)
    My_Debug_function(some_variable)
#endif

ヘッダーで行うことができます

#if !defined(DEBUG) // or #ifndef DEBUG
# define My_Debug_function(some_variable) do { static_cast<void>(some_variable); } while (false)  /* Do nothing */
#endif

したがって、My_Debug_functionほとんど通常。

2
Jarod42