有没有办法控制宏扩展顺序

我希望有人可能知道如何控制/指定宏扩展的顺序。 以下是上下文:

// 32 bit increments, processor has registers for set, clear and invert #define CLR_OFF 1 #define SET_OFF 2 #define INV_OFF 3 #define SET(reg,bits) *((volatile unsigned long*)(& reg+SET_OFF)) = bits //Now if I use this I can do it quite nicely with #define STATUS_LED 0x0040; SET(LATB, STATUS_LED); // LATB is port of the LED. 

我实际上最近不得不将硬件移动很多,所以我决定将LATB信息与STATUS_LED分组,就像这样……

 #define STATUS_LED_PORT LATB #define STATUS_LED_MASK 0x0040; #define STATUS_LED STATUS_LED_PORT, STATUS_LED_MASK //And I try to use it via SET( STATUS_LED ); 

但是,唉,LATB,0x0040被传递给SET宏的参数1。 当不用作宏时,此方法可正常工作:

 inline void SET(u32_t *reg, u32_t bits) { ((volatile u32_t *) (((u32_t)reg) + SET_OFF*4 )) = bits; } //Change the STATUS_LED macro to #define STATUS_LED &STATUS_LED_PORT, STATUS_LED_MASK SET( STATUS_LED); //Works great! 

但不幸的是,我的编译器没有看到需要内联函数并导致6个指令设置寄存器而不是4,所以在bit-banging时使用它是不可预测的。

我希望有人可能知道一种扩展STATUS_LED宏的方法,例如: SET( ##STATUS_LED )

目前我的解决方案是继续使用两个宏SET和SETRM(设置寄存器,掩码),但我觉得应该有一个解决方案,因为SET的代码看起来像……

 #define SETRM(reg,bits) ... #define SET(args) SETRM(args) //WHY WOULD THIS GET EXPANDED HERE?? 

最后,我的处理器的编译器不支持宏的n参数,我想我可以玩那个但是唉:(。

非常感谢您的时间,我会感激任何想法,我可以前进,但如果我可以在任何地方使用SET,那将会更加清晰。

在函数式宏的扩展中替换参数以一种方式发生。 所有在#运算符之后或##任何一侧出现的参数在被替换时都是完全宏扩展的,而不是在扩展类函数宏之前。

这意味着为了使单个宏成为两个宏参数,必须在像宏本身扩展所需的函数之前进行一轮宏替换。

这意味着像宏这样扩展到所需function宏的第二个函数的解决方案是最简单的解决方案。

即给出你原来的SET定义

 #define SET(reg,bits) *((volatile unsigned long*)(& reg+SET_OFF)) = bits 

和一个扩展为两个潜在参数的宏

 #define STATUS_LED_PORT LATB #define STATUS_LED_MASK 0x0040; #define STATUS_LED STATUS_LED_PORT, STATUS_LED_MASK 

您必须使用另一个类似函数的宏来获取所需的替换。

例如

 #define SET2(x) SET(x) 

然后SET2( STATUS_LED )扩展如下。

 SET( LATB , 0x0040; ) 

然后

 *((volatile unsigned long*)(& LATB + 2 )) = 0x0040; 

这是无效的,因为SET宏没有足够的参数; 在参数的任何扩展发生之前,参数与参数匹配。 我的编译器生成错误; 行为未定义。

 SET( STATUS_LED ) 

如果根名称始终相同,则可以使用:

 #define SET_COMPOSITE(root) SET(root##_PORT, root##_MASK)