在C11中,有关键字_Noreturn
这是一个函数说明符(如 inline
是),表示函数不返回——它调用 exit()
或等效的。还有一个标题,<stdnoreturn.h>
,完整的定义是:
7.23
_Noreturn <stdnoreturn.h>
¶1 The header
<stdnoreturn.h>
defines the macronoreturn
which expands to
_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));
问题是如果你包含<stdnoreturn.h>
在翻译单元 (TU) 中,任何后续使用 __attribute__((noreturn))
映射到 __attribute__((_Noreturn))
然后导致编译失败,因为属性 _Noreturn
不被识别(即使关键字被识别为关键字)。也就是说,据我所知,您不能同时使用这两个系统。
除了以下两种方法之外,还有什么方法可以解决这个问题:
- 使用属性的所有代码的大爆炸迁移
<stdnoreturn.h>
, 或 - 使用不太优雅的
_Noreturn
关键字?
- 使用属性的所有代码的大爆炸迁移
您可以通过测试 __STDC_VERSION__ >= 201112L
来检测 C11 — 该值由技术勘误 1 指定,因为标准不小心留下了不完整指定的值:
__STDC_VERSION__
The integer constant 201ymmL.178)178) This macro was not specified in ISO/IEC 9899:1990 and was specified as 199409L in ISO/IEC 9899:1990/Amd.1:1995 and as 199901L in ISO/IEC 9899:1999. The intention is that this will remain an integer constant of type
long int
that is increased with each revision of this International Standard.
这可用于在任何一个头文件中对处理进行条件处理,但如果您混合使用修改过的和未修改的(C11 和 C99)头文件,我似乎遇到了 <stdnoreturn.h>
的棘手问题。 .
- 是否值得向 GCC 提交错误以请求
__attribute__((_Noreturn))
成为__attribute__((noreturn))
的同义词— 这将解决问题。
最佳答案
改为使用 __attribute__((__noreturn__))
。
所有 gcc 属性都有一个 __
版本,这样您就可以在系统头文件中合理地使用它们,而不会污染用户 namespace 。
一些平台提供商似乎也没有意识到这个问题。我最近发现,对于 OS X,他们在宏 __dead2
中有未 protected 版本。
此外,您无法使用 __STDC_VERSION__
宏可靠地检测 C 标准版本。所有具有 C11“测试”版本的 gcc 和 clang 版本如果使用 -std=c11
调用则声明 C11 而没有完全实现它。较新的版本几乎就在那里,但只是差不多。
关于c - 有没有办法在单个翻译单元中理智地使用 GCC __attribute__((noreturn)) 和 <stdnoreturn.h> ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28552467/