2009-10-09 39 views
34

何らかの理由で、私は一時的にいくつかのマクロをヘッダファイルで無効にする必要があり、#undef MACRONAMEはコードをコンパイルしますが、既存のマクロをundefします。C/C++でマクロ展開を一時的に無効にするにはどうすればよいですか?

無効にする方法はありますか?

マクロの値が分からず、クロスコンパイラソリューション(少なくともGCCとMSVCでは動作するはずです)を探しています。

+0

私はあなたが実際にこのマクロ混乱で終わった説得力のある理由があると思いますか?私はここで1つ考えることができませんでした... – sbi

答えて

68

MSVCでは、Microsoft Windowsコンパイラとの互換性のためにpush_macroプラグマ、GCC supportsを使用できます。

#pragma push_macro("MACRONAME") 
#undef MACRONAME 

// some actions 

#pragma pop_macro("MACRONAME") 
+14

それが存在することを知ってうれしい、と良い答えが、それは恐ろしいです。 – Novelocrat

+2

これは、人々が*マクロが悪い*のようなことを私たちに伝え続ける理由です。遅かれ早かれ、ある人が何かばかげたことをする 'new'というマクロを作成しようとしています... –

+1

@JohnLeidegrenまあ、今半分です。 [**悪意のある "悪"マクロの例**](http://stackoverflow.com/q/18167990/319204)。 – TheCodeArtist

27

スタンダードC(C89、C99またはC11)で定義された機能だけを使用すると、「無効」メカニズムは#undefです。

「再有効化」メカニズムがないという問題があります。次いで、;それは任意のtypedefまたは列挙宣言を含まないようにマクロ定義を含むヘッダファイル(関数と変数の宣言を繰り返すことができ、これらを繰り返すことができない)に構成されている場合に他の人が、指摘したように


#undefマクロを有効にしてマクロを使用せずに必要な処理を行った後、再組み込みに対する保護を定義していない可能性があります。

マクロがヘッダーに定義されていない場合は、コードをリファクタリングしてヘッダーに挿入するまでスタックされません。

マクロが機能的なマクロであり、オブジェクトのようなマクロでない場合、他のトリックも利用できます。

#define nonsense(a, b) b /\= a 

int (nonsense)(int a, int b) 
{ 
    return (a > b) ? a : b; 
} 

機能nonsense()は、その直前のマクロにもかかわらず、細かい定義されます。これは、マクロの呼び出し(関数のようなマクロの場合)の直後に、かっこ(空白を入れたり、コメントを含む可能性があります)を付ける必要があるからです。関数定義行では、 'ナンセンス'の後のトークンは閉じ括弧であるため、nonsenseマクロの呼び出しではありません。

マクロは引数なしのオブジェクトのようなマクロされていた、トリックは動作しませんが:

#define nonsense min 

int (nonsense)(int a, int b) 
{ 
    // Think about it - what is the function really called? 
    return (a > b) ? a : b; 
} 

このコードはminと呼ばれる偽の関数を定義し、無意味です。マクロからの保護はありません。

これは、標準が「実装」のために予約されている名前空間を慎重に定義する理由の1つです。インプリメンテーションは、望むか必要なあらゆる目的のために、その名前が実装に予約されていれば、望むまたは必要とする任意のタイプ(機能的またはオブジェクト的)のマクロを定義することができます。実装のサービスのコンシューマーとして、実装に予約されている名前を使用または定義しようとする場合は、コードがおそらくは遅かれ早かれ破綻する可能性があることを認識していなければなりません。実装。

+7

'(ナンセンス)'の回避策のUpvote。驚くばかり! –

1

マクロはいくつかのヘッダーファイルから来ているので、その値にアクセスする必要があります。その後、のような何かを行うことができます

#include <foo.h> // declares macro FOO 

// Do things with FOO 

#undef FOO 

// do things without FOO 

#include <foo.h> // reenable FOO 

あなたのヘッダーは、これらの線に沿って設計されなければならない

#ifndef FOO 
#define FOO do_something(x,y) 
#endif 
+4

そのヘッダーファイルで有効/無効にしているマクロ以外のものがないことを確認してください。そうしないと、再宣言に問題が発生します。 –

+6

また、 ''には再補完から守るために、マントラ '#ifndef FOO_H_INCLUDED/#define FOO_H_INCLUDED/.../#endif'が含まれていないことを確認してください。 –

+2

ヘッダファイルを再組み込みすると、ヘッダファイルがこのように使用するよう特別に設計されていない限り、他の問題が発生する可能性があります。 –

0

EDIT:

あなたはそれが簡単だと思うことがあります。

#ifdef macro 
#define DISABLED_macro macro 
#undef macro 
#endif 

// do what you want with macro 

#ifdef DISABLED_macro 
#define macro DISABLED_macro 
#endif 

しかし、そうではありません(次の例のようにes)!元のヘッダの再を含むマクロに#undefを使用

#include <iostream> 
#include <limits> 

#include <windows.h> 

#ifdef max 
#define DISABLED_max max 
#undef max 
#endif 

int main() 
{ 
    std::cout << std::numeric_limits<unsigned long>::max() << std::endl; 

#ifdef DISABLED_max 
#define max DISABLED_max 
#endif 

    std::cout << max(15,3) << std::endl; // error C3861: "max": identifier not found 
    return 0; 
} 

があるため、ヘッダーガードの、も動作する可能性はありません。 残っているのはpush_macro/pop_macro #pragmaディレクティブです。

#pragma push_macro("MACRO") 
#undef MACRO 
// do what you want 
#pragma pop_macro("MACR") 
+0

40秒ほど私を打ち負かす... – KitsuneYMG

+1

それ以外は動作しますか?マクロを「復元」しないので、「マクロ」に展開されます(欠落部分を追加したときに見えます)。 5月 - 完全な使用例ですか? – UncleBens

+1

これは動作しません - ktsへの私のコメントを参照してください。 – Novelocrat

2

マクロは、私の膝が弱い行かせるが、最も普遍的なソリューションを使用すると、同じソースファイルで再びマクロを再度有効にする必要がないようにあなたのコードを再構築するのではないでしょうか?いくつかのコードを別の関数と別のソースファイルに抽出することはできないでしょうか?問題のマクロをundefすることができます。

+0

申し訳ありませんが、時にはこの問題を回避するコードを変更することはできません。 – sorin

+0

それから、他の答えを見ると、一般的な場合にマクロを「再有効化」する唯一の方法は、元の定義をコピーすることです。 – UncleBens

関連する問題