C 预处理:将定义链接在一起
C Pre-processing: Chaining defines together
我正在尝试根据 if 语句将多个符号连接在一起,但是查看了 SO 并且无法找到不需要将参数传递到我的最后一个宏中的东西。
基本上我正在尝试这样做
#define COMMS_WD_PORT 1
#define COMMS_WD_TXRX CAN_TX
#if COMMS_WD_TXRX == CAN_TX
#define COMMS_WD_REG (uint32_t*)canREG#COMMS_WD_PORT##->TIOC
#else
#define COMMS_WD_REG (uint32_t*)canREG#COMMS_WD_PORT##->RIOC
#endif
我想要的输出
If COMMS_WD_TXRX == CAN_TX
expand COMMS_WD_REG to (uint32_t*)canREG1->TIOC
If COMMS_WD_TXRX == CAN_RX
expand COMMS_WD_REG to (uint32_t*)canREG1->RIOC
我实际得到的
If COMMS_WD_TXRX == CAN_TX
COMMS_WD_REG expands to (uint32_t*)canREG#1->TIOC
If COMMS_WD_TXRX == CAN_RX
COMMS_WD_REG expands to (uint32_t*)canREG#1->RIOC
我对 ## 与 # 的使用以及如何将所有这些正确地链接在一起非常困惑。我看过 gcc 预处理器指南,但它没有接近我正在尝试做的示例。
编辑:我的目标是写入 COMMS_WD_REG 寄存器中的特定位,所以如果有更好的方法来实现我想要的效果,请告诉我
编辑 2:我发现
#define COMMS_WD_REG() (uint32_t*)canREG#COMMS_WD_PORT##->TIOC
COMMS_WD_REG() expands to canREG1->TIOC
这是我想要的输出,但随后我在 COMMS_WD_PORT
处收到错误“需要宏参数名称”
此处的关键部分是您要将标记 canREG
与来自 COMMS_WD_PORT
扩展的标记 1
粘贴在一起。由于用 ##
粘贴的标记通常不受宏扩展的影响,因此您需要双重间接寻址,如 C: Expand Macro With Token Pasting.
中所述
借鉴ouah的例子,我们可以做下面的事情,用一个辅助的CANREG
宏来稍微简化一下:
#define COMMS_WD_PORT 1
#define COMMS_WD_TXRX CAN_TX
#define CAT(x, y) CAT_(x, y)
#define CAT_(x, y) x ## y
#define CANREG CAT(canREG, COMMS_WD_PORT)
#if COMMS_WD_TXRX == CAN_TX
#define COMMS_WD_REG (uint32_t*)CANREG->TIOC
#else
#define COMMS_WD_REG (uint32_t*)CANREG->RIOC
#endif
现在 COMMS_WD_REG
根据需要扩展为 (uint32_t*)canREG1->TIOC
。 Try it on godbolt.
我正在尝试根据 if 语句将多个符号连接在一起,但是查看了 SO 并且无法找到不需要将参数传递到我的最后一个宏中的东西。
基本上我正在尝试这样做
#define COMMS_WD_PORT 1
#define COMMS_WD_TXRX CAN_TX
#if COMMS_WD_TXRX == CAN_TX
#define COMMS_WD_REG (uint32_t*)canREG#COMMS_WD_PORT##->TIOC
#else
#define COMMS_WD_REG (uint32_t*)canREG#COMMS_WD_PORT##->RIOC
#endif
我想要的输出
If COMMS_WD_TXRX == CAN_TX
expand COMMS_WD_REG to (uint32_t*)canREG1->TIOC
If COMMS_WD_TXRX == CAN_RX
expand COMMS_WD_REG to (uint32_t*)canREG1->RIOC
我实际得到的
If COMMS_WD_TXRX == CAN_TX
COMMS_WD_REG expands to (uint32_t*)canREG#1->TIOC
If COMMS_WD_TXRX == CAN_RX
COMMS_WD_REG expands to (uint32_t*)canREG#1->RIOC
我对 ## 与 # 的使用以及如何将所有这些正确地链接在一起非常困惑。我看过 gcc 预处理器指南,但它没有接近我正在尝试做的示例。
编辑:我的目标是写入 COMMS_WD_REG 寄存器中的特定位,所以如果有更好的方法来实现我想要的效果,请告诉我
编辑 2:我发现
#define COMMS_WD_REG() (uint32_t*)canREG#COMMS_WD_PORT##->TIOC
COMMS_WD_REG() expands to canREG1->TIOC
这是我想要的输出,但随后我在 COMMS_WD_PORT
处收到错误“需要宏参数名称”此处的关键部分是您要将标记 canREG
与来自 COMMS_WD_PORT
扩展的标记 1
粘贴在一起。由于用 ##
粘贴的标记通常不受宏扩展的影响,因此您需要双重间接寻址,如 C: Expand Macro With Token Pasting.
借鉴ouah的例子,我们可以做下面的事情,用一个辅助的CANREG
宏来稍微简化一下:
#define COMMS_WD_PORT 1
#define COMMS_WD_TXRX CAN_TX
#define CAT(x, y) CAT_(x, y)
#define CAT_(x, y) x ## y
#define CANREG CAT(canREG, COMMS_WD_PORT)
#if COMMS_WD_TXRX == CAN_TX
#define COMMS_WD_REG (uint32_t*)CANREG->TIOC
#else
#define COMMS_WD_REG (uint32_t*)CANREG->RIOC
#endif
现在 COMMS_WD_REG
根据需要扩展为 (uint32_t*)canREG1->TIOC
。 Try it on godbolt.