C:使用单个#define 传递两个逗号分隔的值
C: Pass two comma separated values with a single #define
问题
微控制器(在我的例子中是 AVR)的 re-usable 模块编程需要通用 IO 引脚的灵活性。每个引脚由一个字母 (A-G) 和一个数字 (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 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__)
问题
微控制器(在我的例子中是 AVR)的 re-usable 模块编程需要通用 IO 引脚的灵活性。每个引脚由一个字母 (A-G) 和一个数字 (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 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__)