例如,如何在源文件中删除“warning: unnamed struct/union that defines no instances
”,而不是通过编译器命令行选项。
我想定义一个C宏CONST_BUG_ON
,我用它在编译时检查一些const值。
#define CONST_BUG_ON(e) struct {int a:!(e);}
它会发出警告warning: unnamed struct/union that defines no instances
,但在这种情况下,这不是一个真正的问题。
感谢Tom Tanner
#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
和第6行文件b
aslo包含CONST_BUG_ON(e),然后gcc抱怨重新定义错误。使用__COUNTER__
__LINE__
的instade可能很完美,但我的旧编译器不支持__COUNTER__
。
感谢Basile Starynkevitch
#define CONST_BUG_ON(e) do { \
int tab[__builtin_constant_p(e)?1:-1] = {0}; \
if (tab[0]) abort(); } while (0)
这是一个C语句,只能放在一个函数中,我真的很想在函数外面使用它。
答案 0 :(得分:3)
解决编译器抱怨的一种方法是你有一个未命名的结构,定义没有实例是给它一个名字:
#define CONST_BUG_ON(e) struct ForDebuggingOnly {int a:!(e);}
获取所需表达式测试的另一种方法是声明(但不定义)如果e
为真,则具有非法大小的数组:
#define CONST_BUG_ON(e) extern int ForDebuggingOnly[(e) ? -1 : 1]
答案 1 :(得分: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];
最后你甚至可以使用MELT(一种用于扩展GCC的高级域特定语言)来定制你的GCC编译器(使用你的特定编译指示),但这需要你几天的工作。
答案 2 :(得分: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__)
这是相当icky但它确实每次使用时都会给出一个唯一的名称(第二级间接可能是虚假的,但这是我在一些经得起时间考验的代码中所拥有的。)
答案 3 :(得分:1)
您尝试的操作看起来像是编译时断言或编译时断言宏。有多种方法可以做到这一点,通常涉及断言失败时具有负维度的数组。许多项目都会调用此宏CT_ASSERT()
,并且a bunch of Stackoverflow questions与它们相关。