在C11中,关键字_Noreturn
是函数说明符(如inline
所示),表示函数未返回 - 它调用exit()
或等效函数。还有一个标题<stdnoreturn.h>
,其完整定义为:
7.23
_Noreturn <stdnoreturn.h>
¶1标题
<stdnoreturn.h>
定义宏noreturn
扩展为
_Noreturn
。
在GNU C(GCC)中,有一个属性__attribute__((noreturn))
基本上完成相同的工作。一个区别是__attribute__((noreturn))
可以出现在函数声明符之前或之后:
extern __attribute__((noreturn)) void err_error(const char *format, ...);
extern void err_error(const char *format, ...) __attribute__((noreturn));
问题是,如果在翻译单元(TU)中包含<stdnoreturn.h>
,__attribute__((noreturn))
的任何后续使用都会映射到__attribute__((_Noreturn))
,这会导致编译失败,因为属性无法识别_Noreturn
(即使关键字被识别为关键字)。也就是说,就我所知,你不能同时使用这两个系统。
除了以下任何一种方法之外,还有什么解决方法:
<stdnoreturn.h>
或_Noreturn
关键字?您可以通过测试__STDC_VERSION__ >= 201112L
来检测C11 - 该值由技术勘误1指定,因为标准意外地保留了未完全指定的值:
__STDC_VERSION__
整数常量 201ymmL 。 178)178)此宏未在ISO / IEC 9899:1990中指定,并被指定为199409L in ISO / IEC 9899:1990 / Amd.1:1995和ISO / IEC 9899:1999中的199901L。意图就是这个 将保留
long int
类型的整数常量,该常量随着每次修订而增加 国际标准。
这可用于在任何一个头文件中调整处理,但如果你混合使用了修改过的(C11和C99)头文件,我似乎遇到了<stdnoreturn.h>
的棘手问题。 / p>
__attribute__((_Noreturn))
成为__attribute__((noreturn))
的同义词 - 这将解决问题。答案 0 :(得分:10)
改为使用__attribute__((__noreturn__))
。
所有gcc属性都有__
版本,这样您就可以在系统标题中合理使用它们,而不会污染用户名空间。
有些平台提供商似乎也没有意识到这个问题。我最近发现,对于OS X,它们在宏__dead2
中具有不受保护的版本。
此外,您无法使用__STDC_VERSION__
宏可靠地检测C标准版本。所有gcc和clang版本都有&#34;测试&#34; C11的版本声称C11,如果使用-std=c11
调用,而没有完全实现它。新版本几乎就在那里,但差不多。
答案 1 :(得分:0)
这正是关键字为_Noreturn
而非noreturn
的原因。不要包含stdnoreturn.h
标题,只需使用:
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
#define noreturn _Noreturn
#elif defined(__GNUC__)
#define noreturn __attribute__((noreturn))
#else
#define noreturn
#endif