我正在为avr gpio编写驱动程序,我有一个函数,它接受一个枚举输入。在将端口名称与" __"连接后,我创建了一个调用此函数的宏。所以我总是可以使用initPort(PORTA,1,...)。
#define initPort(port,mask,dir,pullup) GPIO_Init(port ## __,mask,dir,pullup)
typedef enum {
PORTA__,
PORTB__,
PORTC__,
PORTD__
} PORT;
void GPIO_Init(PORT p, uint8_t pins, Direction dir,uint8_t pullup) {
switch (p) {
case PORTA__:
现在当我想使用我使用的那个函数时:initPort(PORTA,1,...),这很好用。 问题是我想要使用类似的东西:
#define LED_PORT PORTA
initPort(LED_PORT,1,...)
现在发生的事情是GPIO_Init的参数现在是LED_PORT__而不是PORTA__
是否有可能解决这个问题,或者我必须采用其他方式?
答案 0 :(得分:1)
通常的技术是添加一个间接级别,如下所示:
#define PORTNAME(port) port ## __
#define initPort(port, mask, dir, pullup) GPIO_Init(PORTNAME(port), mask, dir, pullup)
typedef enum {
PORTA__,
PORTB__,
PORTC__,
PORTD__
} PORT;
void GPIO_Init(PORT p, uint8_t pins, Direction dir, uint8_t pullup)
{
switch (p)
{
case PORTA__:
break;
}
}
#define LED_PORT PORTA
initPort(LED_PORT, 1, 9, 43)
这可以预处理(我运行cpp port31.c
来获得此输出):
# 1 "port31.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "port31.c"
typedef enum {
PORTA__,
PORTB__,
PORTC__,
PORTD__
} PORT;
void GPIO_Init(PORT p, uint8_t pins, Direction dir, uint8_t pullup)
{
switch (p)
{
case PORTA__:
break;
}
}
GPIO_Init(PORTA__, 1, 9, 43)
这看起来就像你追求的结果。
关于SO的其他问题描述了一般技术。
答案 1 :(得分:1)
你实际上可以通过强制预处理器执行额外的传递来实现它:
#define initPortS(port,mask,dir,pullup) GPIO_Init(port ## __,mask,dir,pullup)
#define initPort(...) initPortS(__VA_ARGS__)
#define LED_PORT PORTA
initPort(LED_PORT,1,2,3);
这样做:
第一遍:
initPort(LED_PORT,1,2,3); -> initPortS(PORTA,1,2,3);
第二遍:
initPortS(PORTA,1,2,3); -> GPIO_Init(PORTA__,1,2,3);
可能的陷阱:
如果PORTA
是定义的符号,它将在第二次传递时得到扩展。所以如果你有一行如
#define PORTA XXX
代码中的某个地方,它将扩展为
GPIO_Init(XXX__,1,2,3);
答案 2 :(得分:0)
你问的是不可能的。但是,您可以创建一个名为LED_PORTinitPort()的函数,并通过将宏的第一个参数连接到initPort()来调用它,它实现了相同的目标。