C 在宏中展开宏
给定以下宏以函数调用方式访问编译器属性,如C 在宏中展开宏,c,macros,c-preprocessor,C,Macros,C Preprocessor,给定以下宏以函数调用方式访问编译器属性,如spec(section(“.mysection”))void foo(void): 我现在想在其他宏中使用这些定义,比如spec(namespace(unmanaged))intx: #define spec_namespace(_H_) spec_namespace_##_H_ #define spec_namespace_unmanaged spec(section(".unmanaged")) 但这根本无法展开,唯一可行的方法是自己编写展开的s
spec(section(“.mysection”))void foo(void)代码>:
我现在想在其他宏中使用这些定义,比如spec(namespace(unmanaged))intx代码>:
#define spec_namespace(_H_) spec_namespace_##_H_
#define spec_namespace_unmanaged spec(section(".unmanaged"))
但这根本无法展开,唯一可行的方法是自己编写展开的spec()宏:
#define spec_namespace_unmanaged spec_section(".unmanaged")
知道发生了什么吗?关于spec(命名空间(非托管))
的gcc-E导致spec(命名空间(非托管))
引用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_)))
与:
请阅读以下内容:
#define spec(_H_) spec_##_H_
#define spec_section(_S_) attribute ((section (_S_)))
#define spec_namespace(_N_) attribute ((namespace (_N_)))
spec(namespace(".unmanaged")) int x;