我已经制作了一些宏来帮助我在gcc项目中设计一个对话框的小部件。 但是我收到了编译错误,所以我做了以下测试:
#define XPOS_ISAFTER(obj) (obj##_XPOS + obj##_XSIZE)
#define PMD_TUTU_XPOS 10
#define PMD_TUTU_XSIZE 10
#define PMD_TUTU2_XPOS XPOS_ISAFTER(PMD_TUTU)
#define PMD_TUTU2_XSIZE 20
#define PMD_TUTU3_XPOS XPOS_ISAFTER(PMD_TUTU2)
int main(void){
int i = 0;
printf("Hello World!\n");
fflush(stdout);
/* Infinite loop */
while (1)
{
i += PMD_TUTU2_XPOS;
i += PMD_TUTU3_XPOS;
}
return 0;
}
当要求预处理器输出时,我得到以下内容:
839 int main(void){
840 int i = 0;
841 printf("Hello World!\n");
842 fflush(stdout);
843
844
845 while (1)
846 {
847 i += (10 + 10);
848 i += (XPOS_ISAFTER(PMD_TUTU) + 20);
849 }
850
851 return 0;
我搜索了一些建议tricks以强制重新扫描,但没有任何结果。 那么预处理器不会扩展这个递归宏吗?
答案 0 :(得分:1)
问题不在于预处理器无法重新扫描,而是在它执行时,它拒绝扩展文本中XPOS_IS_AFTER()
宏的外观,从而导致(间接)从同一宏的先前扩展。换句话说,预处理器不支持宏递归。这由标准明确规定:
[重新扫描宏的替换文本时],如果在替换列表的扫描期间找到要替换的宏的名称(不包括源文件的其余预处理标记),它没有被替换。此外,如果任何嵌套替换遇到要替换的宏的名称,则不会替换它。这些未替换的宏名称预处理令牌不再可用于进一步替换,即使它们稍后(重新)检查其中宏名称预处理令牌将被替换的上下文中。
GCC完全按照您的代码执行操作。你需要一个不同的计划。
答案 1 :(得分:0)
在阅读了Paul F的预处理器技巧之后,经过多次尝试,我得出结论认为它不适用于我的情况,因为我没有明确地编写一个递归宏,因为它似乎是在变通方法中的情况我读了。
所以我写了一些效率低的宏来避免递归:
#define XPOS_ISAFTER(obj) ( obj##_XPOS + obj##_XSIZE )
#define XPOS_ISAFTER2(obj1,obj2) (XPOS_ISAFTER(obj1) + obj2##_XSIZE)
#define XPOS_ISAFTER3(obj1,obj2, obj3) (XPOS_ISAFTER2(obj1, obj2) + obj3##_XSIZE)
#define YPOS_ISUNDER(obj) ( obj##_YPOS + obj##_YSIZE )
#define YPOS_ISUNDER2(obj1,obj2) ( YPOS_ISUNDER(obj1) + obj2##_YSIZE )
#define YPOS_ISUNDER3(obj1, obj2, obj3) ( YPOS_ISUNDER2(obj1,obj2) + obj3##_YSIZE )
#define YPOS_ISUNDER4(obj1,obj2, obj3, obj4) ( YPOS_ISUNDER3(obj1,obj2, obj3) + obj4##_YSIZE )