如何强制宏不展开 [英] How to force macro to not expand

查看:142
本文介绍了如何强制宏不展开的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用以下代码:

#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 一层并将其粘贴到一起,以形成一个已经存在的宏。它的论点。

How can we define CONCATENATE(x) macro to expand only one layer deep. Using two levels of indirection it would expand all the way to pointer to structure, what I want is to expand UART_PERIPH only one layer and paste it together to form an already existing macro from its argument.

可能吗?

推荐答案

我们如何定义CONCATENATE( x)宏仅扩展一层。 ...这可能吗?
How can we define CONCATENATE(x) macro to expand only one layer deep. ... Is this possible?

否。这是您所拥有的。发生宏调用时,第一步是参数替换(a.s .; 6.10.3.1);在此步骤中,如果在宏的替换列表中提到了相应的参数,并且字符串或字符串中没有提及,则对参数中的标记进行评估。产生的扩展将替换替换列表中的所述参数。接下来,不按特定顺序应用串化/粘贴。最后,重新扫描并进行进一步替换(r.a.f.r; 6.10.3.4p1),在此期间,将扫描生成的替换列表本身;在此扫描过程中,宏的名称为涂成蓝色(6.10.3.4p2;蓝色涂成未按名称提及,而是技术行话),这意味着如果遇到该行话就不会进一步扩展。

No. Here's what you have available. When macro invocation occurs, the first step is argument substitution (a.s.; 6.10.3.1); during that step, the tokens in the argument are evaluated if their corresponding parameter is mentioned in the macro's replacement list with said mention not being involved in a stringification or paste. The resulting expansion is substituted for said parameters in the replacement list. Next, stringification/pastes are applied in no particular order. Finally, rescan and further replacement (r.a.f.r; 6.10.3.4p1) occurs, during which the resulting replacement list itself is scanned; during this scan, the macro's name is "painted blue" (6.10.3.4p2; "blue paint" is not mentioned by name but is technical jargon for this), meaning if it's encountered it will not expand further.

所以让我们从这个角度来看。 UART_PERIPH 是一个标识符。在某些情况下,它将被识别为宏(即将触发宏调用),否则将不会。上下文是否在a.s内都没有关系。或r.a.f.r .;如果调用此命令,则调用涉及r.a.f.r。 (没有,因为它是类似对象的)。因此,调用涉及获取 USART2 并对其进行重新扫描。不扩展 USART2 的唯一可能方法是不将该标识符识别为宏,但是由于当前已将其定义为宏,因此唯一的方法用于将此标识符涂成蓝色。这是不可能的(至少在预期的情况下),因为 USART2 必须进行扩展才能实现,并且到那时您已经在注入令牌了,想要。

So let's look at it from this point of view. UART_PERIPH is an identifier. Either it will be recognized as a macro in some context (i.e., will trigger macro invocation), or it will not. It doesn't matter if the context is during an a.s. or a r.a.f.r.; if this is invoked, the invocation involves r.a.f.r. (no a.s. because it's object-like). So the invocation involves taking USART2 and rescanning it. The only possible way for this to not expand USART2 is for this identifier to not be recognized as a macro, but since it's currently defined as one, the only way for that to happen is for this identifier to be painted blue. That's not possible (at least in the intended context) because USART2 would have to be expanding for this to happen, and by that time you're already injecting tokens you don't want.

这篇关于如何强制宏不展开的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆