2009-10-09 23 views
34

出於某種原因,我需要暫時禁用頭文件中的一些宏,並且#undef MACRONAME將使代碼編譯,但它將取消現有的宏。如何暫時禁用C/C++中的宏擴展?

有沒有辦法只是禁用它?

我應該提到你並不真正知道宏的值,並且我正在尋找一個交叉編譯器解決方案(至少應該在GCC和MSVC中工作)。

+0

我想你有一個令人信服的理由,實際上已經結束在這個宏的混亂?我在這裏想不到一個...... – sbi

回答

68

在MSVC中,您可以使用push_macro編譯指示,GCC supports它與Microsoft Windows編譯器兼容。

#pragma push_macro("MACRONAME") 
#undef MACRONAME 

// some actions 

#pragma pop_macro("MACRONAME") 
+14

很高興知道這是存在的,所以很好的答案,但這是可怕的。 – Novelocrat

+2

這就是爲什麼人們不斷告訴我們像*宏是邪惡的東西。遲早有人會創建一個名爲'new'的宏來做一些愚蠢的事情...... –

+1

@JohnLeidegren好吧,我們現在是中途了。 [** misconstrued「邪惡」宏的示例**](http://stackoverflow.com/q/18167990/319204)。 – TheCodeArtist

27

僅使用由標準C(C89,C99或C11)定義的設施,唯一的「禁用」機制是#undef

問題是沒有'重新啓用'機制。


正如其他人指出的那樣,如果包含的宏定義的頭文件(這些不能重複;函數和變量聲明可以重複)結構化,以便它不包含任何的typedef或enum聲明,然後你可以使用#undef這個宏,在沒有生效的宏的情況下做你所需要的,然後重新包含這個頭,可能在定義它的保護以防止重新包含之後。

如果在頭文件中沒有定義這些宏,當然,直到您重構代碼以使它們位於頭文件中,您纔會被卡住。

另一個技巧是可用的 - 如果宏是類似函數的宏而不是類似宏的宏。

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

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

功能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,是無意義的虛假功能。並沒有保護宏觀。

這就是爲什麼標準要小心定義哪些名稱空間是爲'實現'保留的原因之一。如果這些名稱是爲實現保留的,那麼允許實現爲其需要或需要的任何目的定義任何類型的宏(它類似於函數或類似於對象的類型)。如果您作爲The Implementation服務的使用者嘗試使用或定義爲實現保留的名稱,則必須意識到您的代碼遲早可能會中斷,並且這將是您的錯,而不是The實現。

+7

Upvote for'(廢話)'解決方法。真棒! –

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

編輯:

你可以認爲它就是這麼簡單:

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

// do what you want with macro 

#ifdef DISABLED_macro 
#define macro DISABLED_macro 
#endif 

但它不是(就像下面的例子演示ES)!

#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; 
} 

使用在宏觀和再包括原標題#undef也不可能奏效,因爲頭警衛。 所以剩下的就是使用push_macro/pop_macro #pragma指令。

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

打我40秒左右... – KitsuneYMG

+1

除了它工作?是不是它「恢復」了宏,因此它會擴展到「宏」(這是我看到,當我添加缺少的部分)?可能是一個完整的使用示例? – UncleBens

+1

這不起作用 - 請參閱我對kts的評論。 – Novelocrat

2

宏讓我的膝蓋去弱,但不會是最普遍的解決方案是調整你的代碼,這樣你就不需要在同一個源文件中再次重新啓用宏?難道不可能將一些代碼提取到一個單獨的函數和一個單獨的源文件中,在這個文件中可以解開違規的宏。

+0

對不起,但有時您不能修改代碼來解決此問題。 – sorin

+0

我想那時,看其他答案,在一般情況下「重新啓用」宏的唯一方法是複製其原始定義。 – UncleBens