gcc 预编译器指令 __attribute__ ((__cleanup__)) vs ((cleanup)) (带 vs 不带下划线?)
Posted
技术标签:
【中文标题】gcc 预编译器指令 __attribute__ ((__cleanup__)) vs ((cleanup)) (带 vs 不带下划线?)【英文标题】:gcc precompiler directive __attribute__ ((__cleanup__)) vs ((cleanup)) (with vs without underscores?) 【发布时间】:2015-09-25 15:08:17 【问题描述】:我正在学习 gcc 的 cleanup attribute,并学习当变量超出范围时它如何调用要运行的函数,我不明白为什么您可以使用带或不带下划线的“清理”一词. 带有下划线的版本的文档或文档在哪里?
上面的 gcc 文档是这样显示的:
__attribute__ ((cleanup(cleanup_function)))
但是,我阅读的大多数代码示例都是这样显示的:
__attribute__ ((__cleanup__(cleanup_function)))
例如:
http://echorand.me/site/notes/articles/c_cleanup/cleanup_attribute_c.html http://www.nongnu.org/avr-libc/user-manual/atomic_8h_source.html请注意,第一个示例链接表明它们是相同的,当然编码证明了这一点,但他最初是怎么知道的呢?这是哪里来的?
为什么不一样? __cleanup__
在哪里定义或记录,而不是 cleanup
?
我的根本问题在于我不知道我不知道什么,因此我试图暴露我的一些未知的未知数,以便它们成为已知的未知数,直到我可以研究它们并使它们为人所知。
我的想法是,gcc 预处理器指令可能有一些全球适用的原则,您可以在其中任意添加下划线之前或之后? ——或者也许只是其中的一部分? -- 或者它以某种方式修改了预处理器指令或属性,并且在某些情况下,一种方法(带或不带额外下划线)优于另一种方法?
【问题讨论】:
您提供的第一个链接暗示(如果不是直接声明)cleanup
和 __cleanup__
是相同的。此外,鉴于您已将其标记为 C++,我还将提到它的最佳目的似乎是在 C 样式代码中使用 RAII 语义。一般来说,在 C++ 中,您应该将需要清理的东西包装到具有析构函数的类中(并暗示 - 通过 c++11 或更高版本的三规则或五规则 - 您还需要构造函数和/ 或移动运算符)。
谢谢。我进一步阐述了我的问题。第一个链接确实说明它们是相同的,但我想知道这对我使用的其他属性意味着什么……是否总是有多个相同的选项?这家伙怎么知道他们是一样的?当然,这种差异肯定存在某种原因。请参阅我的更新答案,了解我的一些疑惑。
【参考方案1】:
您可以定义宏cleanup
,因为它不是为编译器保留的名称。您不能定义一个名为__cleanup__
的名称。这保证了您使用 __cleanup__
的代码不受其他代码的影响(当然,前提是其他代码的行为)。
【讨论】:
【参考方案2】:正如https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html#Attribute-Syntax 解释的那样:
您可以选择在名称前后使用
__
指定属性名称。这允许您在头文件中使用它们,而不必担心可能的同名宏。例如,您可以使用属性名称__noreturn__
而不是noreturn
。
(但请注意,属性不是预处理器指令。)
【讨论】:
谢谢。如果不是预处理器指令,那么属性是什么?预处理器指令是如何定义的?另外,是否有术语“编译器指令”?这有什么不同? 预处理器指令类似于#include
、#define
、#ifdef
等
那你怎么称呼__attribute__
?如果不是“指令”,那么这类事情的好词是什么?
这是一个(非标准扩展)关键字。以上是关于gcc 预编译器指令 __attribute__ ((__cleanup__)) vs ((cleanup)) (带 vs 不带下划线?)的主要内容,如果未能解决你的问题,请参考以下文章
Linux gcc支持的语法 __attribute__ 属性设置
利用gcc的__attribute__编译属性section子项构建初始化函数表
gcc编译,出现错误:expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ........