2012-08-27 59 views
2

例如,如何在源文件中刪除「warning: unnamed struct/union that defines no instances」,而不是通過編譯器命令行選項。如何關閉C源代碼中的指定警告?

我想定義一個C宏CONST_BUG_ON,我使用它來在編譯時檢查一些常量值。

#define CONST_BUG_ON(e)  struct {int a:!(e);} 

它給出了警告warning: unnamed struct/union that defines no instances,但在這種情況下,它不是一個真正的問題。

感謝湯姆·坦納

#define CONST_BUG_ON_3(e, l) struct buggy##l {int a:!(e);} 
#define CONST_BUG_ON_2(e, l) CONST_BUG_ON_3(e, l) 
#define CONST_BUG_ON(e) CONST_BUG_ON_2(e, __LINE__) 

這很好,但還是有一些問題:如果文件a的第6行包含CONST_BUG_ON(E),並提交a被文件b inclued和文件的第6行b也包含CONST_BUG_ON(e),然後gcc抱怨重新定義了錯誤。使用__COUNTER____LINE__的十六進制可能是完美的,但我的舊編譯器不支持__COUNTER__

由於巴西萊Starynkevitch

#define CONST_BUG_ON(e) do { \ 
    int tab[__builtin_constant_p(e)?1:-1] = {0}; \ 
    if (tab[0]) abort(); } while (0) 

這是一個C語句,只能在一個地方的功能,我真的想用它的功能外。

+0

海報在他的問題中有* GCC *標記 –

+0

爲什麼這對你如此重要?什麼是真正的用例? –

回答

1

假設最近的GCC編譯器,你可以使用__builtin_constant_p

#define CONST_BUG_ON(e) do { \ 
     int tab[__builtin_constant_p(e)?1:-1] = {0}; \ 
     if (tab[0]) abort(); } while (0) 

你對無視警告的一些問題,以測試編譯時間常數,也許,也許GCC diagnostic pragmas可能會有幫助。

如果你希望你的CONST_BUG_ON在聲明上下文只有工作,你可以嘗試

#define CONST_BUG_ON(e) CONST_BUG_AT(e,__LINE__) 
    #define CONST_BUG_AT(e,l) \ 
    extern int tab_##l[__builtin_constant_p(e)?0:-1]; 

最後,你甚至可以定製你的GCC編譯器(與您的特定編譯)也許使用MELT(高一級域名特定的語言來擴展GCC),但是這會花費你數天的時間。解決編譯器的投訴

3

的一種方式是,你未定義任何實例的無名結構是給它一個名字:

#define CONST_BUG_ON(e)  struct ForDebuggingOnly {int a:!(e);} 

的另一種方法來獲取表達測試你想要的是聲明(但不是定義)具有非法大小,如果e是真正的數組:

#define CONST_BUG_ON(e) extern int ForDebuggingOnly[(e) ? -1 : 1] 
+0

如果多次使用CONST_BUG_ON,這段代碼不起作用,gcc會抱怨重新定義錯誤。 –

+0

@yangwen:使用第二種方法,使用'extern int'。 –

1

你可以使用宏魔術通過傳遞的行號,給自己一個唯一的ID

#define CONST_BUG_ON_3(e, l) struct buggy##l {int a:!(e);} 
#define CONST_BUG_ON_2(e, l) CONST_BUG_ON_3(e, l) 
#define CONST_BUG_ON(e) CONST_BUG_ON_2(e, __LINE__) 

這是相當噁心的,但它確實每次使用時都會給出一個獨特的名稱(第二級間接可能是虛假的,但這是我在一些經過時間考驗的代碼中所具有的)。

+1

這很好,但仍有一些問題:如果文件「a」的第6行包含「CONST_BUG_ON(e)」,並且文件「a」被文件「b」包含,並且文件「b」的第6行也包含'CONST_BUG_ON(e)',然後gcc抱怨重新定義錯誤。使用__LINE__的'__COUNTER__'即可完美,但我的舊編譯器不支持'__COUNTER__'。 –

+0

我認爲如果您有像這樣設置的源代碼,您可能會遇到其他問題。 –

1

它看起來像你試試所謂的編譯時間斷言編譯時斷言宏。有很多種方法可以做到這一點,通常涉及斷言失敗時負數維的數組。許多項目調用這個宏CT_ASSERT(),並有a bunch of Stackoverflow questions與他們有關。