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