在宏中展开宏

时间:2014-07-28 08:30:11

标签: c macros c-preprocessor

给定以下宏以函数调用方式访问编译器属性,如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")

知道发生了什么事吗? spec(namespace(unmanaged))上的gcc -E会产生spec(namespace(unmanaged))

1 个答案:

答案 0 :(得分:1)

引用C99草案6.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;