繁体   English   中英

C:用一个#define传递两个逗号分隔的值

[英]C: Pass two comma separated values with a single #define

问题

为微控制器编程可重用模块(在我的情况下为AVR)需要一般IO引脚的灵活性。 每个引脚由字母(AG)和数字(0-7)定义。 然而,它由三个寄存器中相同位置的一位控制。 因此配置文件需要包含四个条目(指向寄存器的3个指针+ 1个位置),这不是那么优雅。

简单的解决方法是简单地接受这个,但由于这是一个常见的问题,它至少应该得到一点关注。


想法

让预编译器像这样重复工作会很好:

//CONFIGURATION
#define IO_NAME B5

//MACRO
#define PORT_(ID)
#define PIN_(ID)
#define DDR_(ID)
#define BIT_(ID)

结果应如下所示

PORT_(IO_NAME)   =>  PORTB
PIN_(IO_NAME)    =>  PINB
DDR_(IO_NAME)    =>  DDRB
BIT_(IO_NAME)    =>  5

结果表达式在AVR Studio中定义。


我试过的

我无法弄清楚如何忽略字母而不是数字,所以我尝试了连接:

#define PORT_(REG, BIT)             PORT_2(REG, BIT)
#define PIN_(REG, BIT)              PIN_2(REG, BIT)
#define DDR_(REG, BIT)              DDR_2(REG, BIT)

#define PORT_2(REG, BIT)            (PORT ## REG)
#define PIN_2(REG, BIT)             (PIN ## REG)
#define DDR_2(REG, BIT)             (DDR ## REG)

#define BIT(REG, BIT)               (BIT)

额外的层需要使用任何#defined值作为REG或BIT。

以下代码按预期工作:

#define IO_NAME_REG B
#define IO_NAME_BIT 5

PORT_(B, 5)                           => PORTB
PORT_(IO_NAME_REG, IO_NAME_BIT)       => PORTB


但是,当我尝试

#define IO_NAME B, 5
PORT_(IO_NAME)

它导致错误:

macro "PORT_" requires 2 arguments, but only 1 given

据我所知,逗号被解释为逗号运算符,因此忽略左值。 我从这个实验得出结论:

#define IO_NAME B, 5
PORT_(IO_NAME,)                      => PORT_5


用define替换逗号:

#define comma ,
#define IO_NAME B comma 5
PORT_(IO_NAME,)                      => PORT_5

导致相同的结果


解决方法

当然,可以将'B'和'5'分成两个单独的定义。 虽然这是一个超过四个定义的改进,但它仍然不那么舒服。


问题

......并不严格限于标题。 任何更短或更简单的解决方案

#define IO_NAME_REG B
#define IO_NAME_BIT 5
PORT_(IO_NAME_REG, IO_NAME_BIT)       => PORTB

欢迎来到我这里。

如果这根本不可能,我想知道原因。

这应该做你想要的:

#include <stdio.h>

#define IO_NAME B, 5

#define PORT_(arg)  PORT_2(arg)
#define PIN_(arg)   PIN_2(arg)
#define DDR_(arg)   DDR_2(arg)
#define BIT_(arg)   BIT_2(arg)

#define PORT_2(reg, bit)    (PORT ## reg)
#define PIN_2(reg, bit)     (PIN ## reg)
#define DDR_2(reg, bit)     (DDR ## reg)
#define BIT_2(reg, bit)     (bit)

#define PORTB   1
#define PINB    2
#define DDRB    3

int main()
{
    printf("%d\n", PORT_(IO_NAME));
    printf("%d\n", PIN_(IO_NAME));
    printf("%d\n", DDR_(IO_NAME));
    printf("%d\n", BIT_(IO_NAME));

    return 0;
}

这会产生以下输出:

1
2
3
5

宏体中的##使预处理器通过连接操作数来创建新的标记。

这几乎就是你所拥有的。 不同之处在于您的顶级宏需要采用单个参数,而辅助宏需要两个。

您可以使用可变参数宏,只需更改即可实现目标。

#define PORT_(...)             PORT_2(__VA_ARGS__)
#define PIN_(...)              PIN_2(__VA_ARGS__)
#define DDR_(...)              DDR_2(__VA_ARGS__)

暂无
暂无

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

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