使用以下代码:
#include <stdio.h>
typedef struct
{
int APB1ENR;
int b;
int c;
} RCC_TypeDef;
typedef struct
{
int a;
int b;
int c;
} USART_TypeDef;
#define USART2_BASE 0x1000
#define USART2 ((USART_TypeDef *) USART2_BASE)
#define RCC_BASE 0x2000
#define RCC_APB1ENR_USART2EN_Pos (17U)
#define RCC_APB1ENR_USART2EN_Msk (0x1UL << RCC_APB1ENR_USART2EN_Pos)
#define RCC_APB1ENR_USART2EN RCC_APB1ENR_USART2EN_Msk
#define RCC ((RCC_Typedef *) RCC_BASE)
#define SET_BIT(REG, BIT) ((REG) |= (BIT))
#define __HAL_RCC_USART2_CLK_ENABLE() SET_BIT(RCC->APB1ENR, (RCC_APB1ENR_USART2EN))
#define UART_PERIPH USART2
#define CONCATENATE(x) // What comes here??
int main()
{
CONCATENATE(UART_PERIPH);
// | should expand to __HAL_RCC_USART2_CLK_ENABLE();
}
我们如何定义CONCATENATE(x)
宏以仅扩展一层深度。使用两个间接级别,它将一直扩展到结构指针,我想要的是仅扩展UART_PERIPH
一层并将其粘贴到一起,以根据其参数形成一个已经存在的宏。
这可能吗?
答案 0 :(得分:3)
我们如何定义CONCATENATE(x)宏以仅扩展一层深度。 ...这可能吗?
不。这是您所拥有的。发生宏调用时,第一步是参数替换(a.s .; 6.10.3.1);在该步骤中,如果在宏的替换列表中提到了它们的相应参数,而字符串或粘贴中没有提及,则对参数中的标记进行评估。生成的扩展将替换替换列表中的所述参数。接下来,不按特定顺序应用串化/粘贴。最后,重新扫描并进行进一步替换(r.a.f.r; 6.10.3.4p1),在此期间,将扫描生成的替换列表本身;在此扫描过程中,宏的名称为“涂成蓝色”(6.10.3.4p2;“蓝色涂成”的名称未提及,但technical jargon),这意味着如果遇到该宏,它将不会进一步扩展。>
所以让我们从这个角度来看它。 UART_PERIPH
是一个标识符。在某些情况下它将被识别为宏(即将触发宏调用),否则将不会。上下文是否在a.s中都没有关系。或r.a.f.r .;如果调用此命令,则调用涉及r.a.f.r。 (不可以,因为它是类似对象的)。因此,调用涉及获取USART2
并重新扫描。不扩展USART2
的唯一可能方法是不将该标识符识别为宏,但是由于当前已将其定义为宏,因此唯一的实现方式是将该标识符涂成蓝色。这是不可能的(至少在预期的情况下),因为USART2
必须进行扩展才能做到这一点,并且到那时您已经在注入不需要的令牌。