我的代码包含很多行,例如:
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语句可以在函数外部使用,该语句以分号结尾并且可以重复使用?
答案 0 :(得分:3)
我想在没有实现static_assert的编译器上进行编译。因此,我希望这些行变为无操作。
为什么不将Lundin的答案(检查当前的编译器是否已实现)与static_assert
的实现结合起来(这并不难做到) )?
/* 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
。