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->TIOCTry it on godbolt.