c - 有没有办法在单个翻译单元中理智地使用 GCC __attribute__((noreturn)) 和 <stdnoreturn.h> ?

标签 c gcc clang c11

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

7.23 _Noreturn <stdnoreturn.h>

¶1 The header <stdnoreturn.h> defines the macro

noreturn

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不被识别(即使关键字被识别为关键字)。也就是说,据我所知,您不能同时使用这两个系统。

  • 除了以下两种方法之外,还有什么方法可以解决这个问题:

    1. 使用属性的所有代码的大爆炸迁移 <stdnoreturn.h> , 或
    2. 使用不太优雅的 _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/

相关文章:

c - "*((char*)-1) = ' x';"代码是什么意思?

c++ - OpenSSL Boost context.use_private_key_file 和 context.use_rsa_private_key_file 无一异常(exception)地终止程序

c - gcc 宏中的类型检查和类型衰减

c++ - -mmacosx-version-min 影响位域的打包行为?

c - 如何仅从 clang AST 获取函数声明?

c++ - LLVM 上的内联 ASM 中的 "Invalid symbol redefinition"

c - 如何将 memmove 与指针的指针一起使用?

c - 我在哪里可以找到在 c 标准头文件(如 stdlib.h)中声明的函数的定义?

我可以在 C 中执行类似 #define ARRAY(size) char[##size##] 的操作吗?

java - Arduino 与 Java 接口(interface)问题