C没有op语句的外部函数

时间:2018-08-30 11:02:57

标签: c preprocessor

我的代码包含很多行,例如:

static_assert(sizeof(my_stuct)==42, "check struct size");

,我想在没有实现static_assert的编译器上进行编译。因此,我希望这些行变为无操作。我尝试过:

#define static_assert(COND, MSG) 

它工作正常,但我收到了clang编译器警告:

warning: extra ';' outside of a function [-Wextra-semi]

是否有一个简单的no-op C语句可以在函数外部使用,该语句以分号结尾并且可以重复使用?

4 个答案:

答案 0 :(得分:3)

  

我想在没有实现static_assert的编译器上进行编译。因此,我希望这些行变为无操作。

为什么不将Lundin的答案(检查当前的编译器是否已实现)与static_assert实现结合起来(这并不难做到) )?

PDCLib(已获得CC0许可)中复制实现:

/* with dodgy implementations, you could also #ifndef static_assert */
#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
#define _PDCLIB_cc( x, y )     x ## y
#define _PDCLIB_concat( x, y ) _PDCLIB_cc( x, y )

#define static_assert( e, m ) enum { _PDCLIB_concat( _PDCLIB_assert_, __LINE__ ) = 1 / ( !!(e) ) }
#endif

对于给定的表达式e和消息m,它声明一个匿名枚举,其中一个成员的名称与当前源文件行(_PDCLIB_assert_串联在一起的__LINE__(因此每个源文件可以有多个static_assert()。如果表达式1为真,则将该成员设置为1除以e,如果表达式为false,则将该成员除以0,这将导致对a的输出断言失败:

./path/to/source.c:57:94: warning: division by zero [-Wdiv-by-zero]
 #define static_assert( e, m ) enum { _PDCLIB_concat( _PDCLIB_assert_, __LINE__ ) = 1 / ( !!(e) ) }
                                                                                      ^

./path/to/header.h:571:1: note: in expansion of macro 'static_assert'
 static_assert( false, "test" );
 ^
./path/to/source.c:57:62: error: enumerator value for '_PDCLIB_assert_571' is not an integer constant
...

虽然不漂亮,但完全符合C89,经过测试且可维修。

可以从_PDCLIB_*重命名为您喜欢的任何名称。

答案 1 :(得分:2)

到目前为止,我的解决方案是

#define static_assert(COND, MSG) extern int __static_assert_dummy__

工作正常,但对我来说似乎很丑!

答案 2 :(得分:2)

仅进行了非常快速的测试,但是如何呢?

#define static_assert(COND, MSG) extern int _no_static_assertion

还是什么?重复extern应该没问题。

答案 3 :(得分:2)

由于这是C11的功能,因此答案很简单:只需检查编译器是否支持C11。

#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112
  static_assert(sizeof(my_stuct)==42, "check struct size");
#endif 

相反的是,在没有标准C的情况下使其成为无操作,从而消除了对上述编译器开关到处都是的需求,

#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112
  #define static_assert(cond, str) struct dummy_t
#endif 

请记住,与C11关键字static_assert不同,#include <assert.h>需要_Static_assert