繁体   English   中英

c预处理程序宏在扩展后连接参数

[英]c preprocessor macro concatenate arguments after expansion

我正在编写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__

是否有可能解决此问题,或者我必须使用其他方式?

通常的技术是添加一个间接级别,如下所示:

#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的其他问题描述了通用技术。

您实际上可以通过强制预处理器在执行以下操作之前执行额外的操作:

#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);

您要问的是不可能的。 但是,您可以创建一个名为LED_PORTinitPort()的函数,并通过将宏的第一个参数与initPort()关联来调用它,这可以实现相同的目标。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM