有没有办法在单个翻译单元中使用GCC __attribute __((noreturn))和<stdnoreturn.h>?

Jon*_*ler 10 c gcc clang c11

在C11中,有一个关键字_Noreturn,它是一个函数说明符(如inlineis),表示函数不返回 - 它调用exit()或等效.还有一个标题,<stdnoreturn.h>完整的定义是:

7.23 _Noreturn <stdnoreturn.h>

1标题<stdnoreturn.h>定义宏

noreturn
Run Code Online (Sandbox Code Playgroud)

扩展到_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));
Run Code Online (Sandbox Code Playgroud)

问题在于,如果<stdnoreturn.h>在转换单元(TU)中包含任何后续使用的__attribute__((noreturn))get映射__attribute__((_Noreturn)),则会导致编译失败,因为_Noreturn无法识别该属性(即使关键字被识别为关键字).也就是说,据我所知,你不能同时使用这两个系统.

  • 有没有办法解决这个问题,除了:

    1. 使用要使用的属性的所有代码的大爆炸<stdnoreturn.h>,或
    2. 使用不完全优雅的_Noreturn关键字?

您可以通过测试检测C11 __STDC_VERSION__ >= 201112L- 该值由技术勘误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)头文件,我似乎遇到了棘手的问题<stdnoreturn.h>.

  • 是否值得向GCC提交一个错误,要求将__attribute__((_Noreturn))其作为同义词__attribute__((noreturn))- 这将解决问题.

Jen*_*edt 13

__attribute__((__noreturn__))改用.

所有gcc属性都有一个__版本,您可以在系统标头中合理地使用它们,而不会污染用户名空间.

一些平台提供商似乎也没有意识到这个问题.我最近发现,对于OS X,它们在宏中具有不受保护的版本__dead2.

此外,您无法使用__STDC_VERSION__宏可靠地检测C标准版本.所有gcc和clang版本都有C11的"测试"版本,如果在-std=c11没有完全实现的情况下调用C11则声称它.新版本几乎就在那里,但差不多.