在宏中展开宏

朱利奥·瓜拉(Julio Guerra)

给定以下宏,以函数调用方式提供对编译器属性的访问,例如spec(section(".mysection")) void foo(void);

#define spec(_H_) spec_##_H_
#define spec_section(_S_) attribute ((section (_S_)))

我现在想在其他宏中使用这些定义,例如spec(namespace(unmanaged)) int x;

#define spec_namespace(_H_) spec_namespace_##_H_
#define spec_namespace_unmanaged spec(section(".unmanaged"))

但这根本不会扩展,使其起作用的唯一方法是自己编写扩展的spec()宏:

#define spec_namespace_unmanaged spec_section(".unmanaged")

知道发生了什么吗?gcc -E on的spec(namespace(unmanaged))结果spec(namespace(unmanaged))

格热哥兹·斯佩特科夫斯基

引用C996.10.3.4 重新扫描草案并进一步替换§2(重点是我的):

如果在此扫描替换列表的过程中找到了要替换的宏的名称(不包括源文件的其余预处理令牌),则不会替换该宏。此外,如果任何嵌套的替换遇到要替换的宏的名称,则不会替换这些未替换的宏名称预处理令牌不再可用于进一步替换,即使它们后来在本来会被替换的宏名称预处理令牌的上下文中进行了(重新)检查。

根据以下宏定义:

#define spec(_H_) spec_##_H_
#define spec_namespace(_H_) spec_namespace_##_H_
#define spec_namespace_unmanaged spec(section(".unmanaged"))

显然,spec宏被评估了两次,因此没有进一步的替换,让我们逐步进行:

spec(namespace(unmanaged)) int x; → spec_namespace(unmanaged) int x;
spec_namespace(unmanaged) int x;  → spec_namespace_unmanaged int x;
spec_namespace_unmanaged int x;   → spec(section(".unmanaged")) int x;

您可以做的就是将您的最后一个宏定义修改为以下形式:

#define spec_namespace_unmanaged attribute ((namespace (".unmanaged")))

或简化为:

#define spec(_H_) spec_##_H_
#define spec_section(_S_) attribute ((section (_S_)))
#define spec_namespace(_N_) attribute ((namespace (_N_)))

和:

spec(namespace(".unmanaged")) int x;

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章