2012-09-28 53 views
29

我想在#warning指令中打印宏值(展開宏)。C預處理器:在#warning中擴展宏

例如,代碼:

#define AAA 17 
#warning AAA = ??? 

所需的編譯時輸出將

warning: AAA = 17 

我用什麼???,或者,我怎麼增加的代碼?

+1

據1999年的C標準,你只有'#error'類似的東西並且它不擴展任何宏,它只是逐字打印文本並導致編譯停止。無論如何,你想用這個來達到什麼目的? –

+0

我有許多makefile的層次結構,它們以各種方式定義AAA,具體取決於make目標參數。我想驗證該定義對於目標是否正確。我不想創建一個#if AAA = 1 ... #warning「是1」的列表... – elomage

+0

此外,這是針對沒有顯示器的嵌入式世界,所以我不能輕易測試宏值增加一些像printf(#AAA);並在運行時檢查它。 – elomage

回答

37

您可以使用預處理指令#pragma message

實施例:

#define STR_HELPER(x) #x 
#define STR(x) STR_HELPER(x) 

#define AAA 123 
#pragma message "content of AAA: " STR(AAA) 

int main() { return 0; } 

輸出可以是這樣的:

$ gcc test.c 
test.c:5:9: note: #pragma message: content of AAA: 123 
#pragma message("content of AAA: " STR(AAA)) 
     ^

參考:

+0

你應該提及這個工作的編譯器。 '#pragma's'是特定於實現的。 –

+0

使用gcc版本4.5.3(GNU GCC補丁mspgcc-20110716),謝謝。 – elomage

+2

務必使用'#pragma message'而不是'#message'或'#warning' – fantastory

2

很多時候,我有我的Makefile生成一個本地generated.h文件,其中包含所需的定義。

 
generated.h: Makefile 
     echo >generated.h "// WARNING: generated file. Change Makefile instead" 
     date >>generated.h '+// generated on %Y-%m-%d %H:%M:%S' 
     echo >>generated.h "#if AAA == AAA_bad" 
     echo >>generated.h "#warning \"AAA = $(AAA_bad)\"" 
     echo >>generated.h "#endif"

需要#include「generated.h」很明顯。

當然,你可以在這裏任意旋轉的複雜性,但如果它得到更多,那麼你可能 希望把複雜到一個單獨的腳本雜亂Makefile文件可以是一個可怕的 維護問題的幾行。有了一點想象力,你就可以有循環從一點輸入產生大量的測試。

具有generated.h目標取決於Makefile對於確保如果目標中的指令發生變化而重新生成generated.h很關鍵。如果你有一個單獨的generated.sh腳本,它也將在依賴列表上。

免責聲明:尚未測試真實。

7

我不推薦使用#warning後,因爲它不是標準C.另外,要警惕,但不會引發錯誤反對什麼呢?警告通常是編譯器在你做一些可疑的事情時所使用的,這些事情是我們直接危險的,但是C標準允許的。在正常的應用中你沒有這種情況,你希望它可以完美地編譯,也可以根本不編譯。因此我會使用標準的#error而不是非標準的#warning。

您無法鍵入預處理器定義的實際內容。這樣的東西可能就足夠了:

#if (AAA < SOMETHING) && (AAA > SOMETHING_ELSE) 
    #error AAA is bad. 
#endif 

我認爲這對程序員來說足夠詳細了。但是,如果您真的需要需要更多詳細信息並且您有現代C編譯器,則可以使用static_assert。然後你就可以實現了接近你想要什麼:

#include <assert.h> 

#define xstr(s) str(s) 
#define str(s) #s 
#define err_msg(x) #x " is " xstr(x) 

#define AAA 17 

static_assert(AAA != 17, err_msg(AAA)); 

這個宏爛攤子應該打印AAA是17.在如何將這些宏的工作可以發現here的解釋。

我不確定static_assert是否包含在C99或C11中,它肯定是在C11中。您可能需要使用一些GCC擴展來啓用它。

+0

另請參閱[此問題](http://stackoverflow.com/q/3385515/1025391)靜態斷言在C – moooeeeep

+0

我只需要一個信息性的消息與值來確認我懷疑全局內部參數是不正確的特殊案例。這裏沒有「壞」的價值。原來,這是不正確的。但是,感謝static_assert,它起作用自g ++版本4.3並帶有選項-std = C++ 0x,而gcc版本4.6有static_assert別名爲_Static_assert而沒有選項。 – elomage

+0

@elomage自C11以來,_Static_assert實際上是C中的一個關鍵字。 包含一個宏static_assert,它擴展爲_Static_assert。任何一種形式都應該很好用,因爲它們都是標準的。 – Lundin

7

如果您確實想發出警告,以下內容也可以使用。然而,這取決於被啓用C99(用gcc 4.8.2作品或更高版本,而不是在早期版本的測試):

#define N 77 

#define __STRINGIFY(TEXT) #TEXT 
#define __WARNING(TEXT) __STRINGIFY(GCC warning TEXT) 
#define WARNING(VALUE) __WARNING(__STRINGIFY(N = VALUE)) 

#if N == 77 
_Pragma (WARNING(N)) 
#endif