有没有办法来控制宏扩展秩序 [英] Is there a way to control macro expansion order
问题描述
我希望有人可能对如何控制/指定宏扩展的顺序的想法。这里是上下文:
I am hoping that someone may have an idea on how to control/specify the order of macro expansion. Here is the context:
// 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.
其实我已经不得不四处相当多的移动硬件为晚,所以我决定组与STATUS_LED像这样的LATB信息...
I've actually had to move hardware around quite a bit as of late so I decided to group the LATB info with the STATUS_LED like so...
#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。当不作为宏观这种方法正常工作:
But alas, LATB,0x0040 is passed to argument 1 of the SET macro. When not used as a macro this method works properly:
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,所以使用,而位敲打它是联合国predictable。
But unfortunately my compiler doesn't see the need to inline the function and causes 6 instructions to set the register as opposed to 4, so for use while bit-banging it is unpredictable.
我希望有人可能知道的一种方式,扩大STATUS_LED宏观第一,是这样的: SET(## STATUS_LED)
I am hoping someone may know of a way to expand the STATUS_LED macro first, something like:
SET( ##STATUS_LED )
目前我的解决办法继续前进是有两个宏SET和SETRM(设置寄存器,面膜),但我觉得应该有一个解决方案,因为code为SET样子...
Currently my solution to move on is to have two macros SET, and SETRM (set register, mask) but I feel like there should be a solution because the code for SET looks like...
#define SETRM(reg,bits) ...
#define SET(args) SETRM(args) //WHY WOULD THIS GET EXPANDED HERE??
最后,我的处理器的编译器不支持正参数宏,我想我也许能与玩,但很可惜:(
And lastly, my processor's compiler does not support n-arguments to a macro, I thought I might be able to play with that but alas :(.
非常感谢您的宝贵时间,我会AP preciate任何想法,我可以向前移动,但它是如此干净多了,如果我可以只使用SET无处不在。
Thank you very much for your time, and I would appreciate any thoughts, I can move forward, but it would be so much cleaner if I could just use SET everywhere.
推荐答案
在的函数宏扩展参数替换发生在一组的方式。其中,#
运营商或一个 ##
完全展开宏观两侧后不会出现所有的参数,当他们被替换时,函数宏被扩展而不是之前。
Substitution of parameters in the expansion of function-like macros happens in a set way. All arguments which don't appear after the #
operator or either side of a ##
are fully macro expanded when they are replaced, not before the function-like macro is expanded.
这意味着使一个单一的宏观成了两队宏参数一轮宏替换必须出现类似宏所需要的功能本身扩大了。
This means that to make a single macro become two macro arguments a round of macro substitution must occur before the required function like macro is itself expanded.
这意味着,一个第二功能的类似宏它扩展到所需的函数宏溶液是最简单的解决办法。
This means that the solution of a second function like macro that expands to the desired function-like macro is the simplest solution.
即。鉴于你原来的 SET
定义
#define SET(reg,bits) *((volatile unsigned long*)(& reg+SET_OFF)) = bits
和扩展为两个潜在的参数的宏
and a macro that expands to two potential arguments
#define STATUS_LED_PORT LATB
#define STATUS_LED_MASK 0x0040;
#define STATUS_LED STATUS_LED_PORT, STATUS_LED_MASK
您必须使用另一个函数宏来获取你所需要的替换。
You have to use another function-like macro to get the substitution that you need.
例如
#define SET2(x) SET(x)
然后 SET2(STATUS_LED)
扩展如下。
SET( LATB , 0x0040; )
然后
*((volatile unsigned long*)(& LATB + 2 )) = 0x0040;
这是无效的,因为没有足够的参数传递给 SET
宏;争论的任何膨胀发生之前的参数相匹配的参数。我的编译器会生成一个错误;的行为没有定义
This isn't valid as there are not enough arguments to the SET
macro; the parameters are matched to arguments before any expansion of the argument occurs. My compiler generates an error; the behaviour isn't defined.
SET( STATUS_LED )
这篇关于有没有办法来控制宏扩展秩序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!