C 在函数外没有 op 语句
C no op statement outside functions
我的代码包含很多行,例如:
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]
是否有一个简单的无操作 C 语句可以在函数外部使用,它以分号终止并且可以重复使用?
目前我的解决方案:
#define static_assert(COND, MSG) extern int __static_assert_dummy__
工作正常但我觉得很丑!
只测试了很快,但是怎么样:
#define static_assert(COND, MSG) extern int _no_static_assertion
什么的?重复 extern
应该没问题。
由于这是 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
不过请记住 static_assert
需要 #include <assert.h>
,这与 C11 关键字 _Static_assert
不同。
I want to compile on a compiler which has no static_assert implemented. So I want these lines to become no-op.
为什么不将 Lundin 的答案(检查当前编译器 是否实现了 )与 [=12= 的 实现 结合起来](这不难做到)?
从 PDCLib (which is 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()
)。如果表达式 e
为真,则此成员设置为 1
除以 1
,如果表达式为假,则此成员设置为除以 0
,这将导致像这样的输出断言失败:
./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_*
重命名为您喜欢的任何名称。
我的代码包含很多行,例如:
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]
是否有一个简单的无操作 C 语句可以在函数外部使用,它以分号终止并且可以重复使用?
目前我的解决方案:
#define static_assert(COND, MSG) extern int __static_assert_dummy__
工作正常但我觉得很丑!
只测试了很快,但是怎么样:
#define static_assert(COND, MSG) extern int _no_static_assertion
什么的?重复 extern
应该没问题。
由于这是 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
不过请记住 static_assert
需要 #include <assert.h>
,这与 C11 关键字 _Static_assert
不同。
I want to compile on a compiler which has no static_assert implemented. So I want these lines to become no-op.
为什么不将 Lundin 的答案(检查当前编译器 是否实现了 )与 [=12= 的 实现 结合起来](这不难做到)?
从 PDCLib (which is 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()
)。如果表达式 e
为真,则此成员设置为 1
除以 1
,如果表达式为假,则此成员设置为除以 0
,这将导致像这样的输出断言失败:
./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_*
重命名为您喜欢的任何名称。