2

例如,我怎样才能摆脱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,但在这种情况下,它不是一个真正的问题。

谢谢汤姆坦纳

#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__)

这很好,但仍然存在一些问题:如果 filea的第 6 行包含 CONST_BUG_ON(e),并且 file 包含a在 file 中b,并且文件的第 6 行也b包含 CONST_BUG_ON(e),则 gcc 会抱怨重新定义错误。使用__COUNTER__instade__LINE__可能完美,但我的旧编译器不支持__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语句,只能放在函数中,我很想在函数外使用它。

4

4 回答 4

3

解决编译器投诉的一种方法是您有一个未定义任何实例的未命名结构是给它一个名称:

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

获取所需表达式测试的另一种方法是声明(但不定义)一个具有非法大小的数组(如果e为真):

#define CONST_BUG_ON(e)    extern int ForDebuggingOnly[(e) ? -1 : 1]
于 2012-08-27T13:11:30.523 回答
1

看起来您尝试的方法称为编译时断言编译时断言宏。有多种方法可以做到这一点,通常在断言失败时涉及具有负维度的数组。许多项目都调用这个宏CT_ASSERT(),并且有一堆与它们相关的 Stackoverflow 问题。

于 2012-08-27T13:25:48.107 回答
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 诊断编译指示会有所帮助。

如果您希望您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 编译器(使用您的特定 pragma),但这将花费您数天的时间。

于 2012-08-27T12:47:06.710 回答
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__)

这相当恶心,但每次使用时都会给出一个唯一的名称(第二级间接可能是虚假的,但这是我在一些经受住时间考验的代码中所拥有的)。

于 2012-08-27T13:17:51.007 回答