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