C语言宏代码——#define with 2 '##'
C language macro code - #define with 2 '##'
我最近遇到这个问题,找不到解释的支持文档或数据。问题是问我的,那个人不愿意分享答案。
#define BIT(A) BIT_##A
#define PIN_0 0
"Do we get BIT_0 by using macro BIT(PIN_0)? If no make necessary corrections?"
我不知道上面问题的答案?
宏
#define BIT(A) BIT_##A
表示从两个 单独的 令牌创建一个 单个 令牌。如果不使用 ##
(令牌连接运算符),您可能会想执行以下操作之一:
#define BIT(A) BIT_A
#define BIT(A) BIT_ A
第一个问题是,因为 BIT_A
已经是单个标记,所以将 A
与传递的参数匹配的尝试不会成功,您将得到文字扩展BIT_A
无论您什么 作为参数使用:
BIT(42) -> BIT_A
第二个问题是,即使 A
是一个单独的标记,因此 将 进行替换,最终扩展将 不是是一个单一的令牌:
BIT(42) -> BIT_ 42
宏中的 ##
采用 A
指定的 值 ,并将其附加到文字 BIT_
上,形成一个标记,因此,例如,
BIT(7) -> BIT_7
BIT(PIN0) -> BIT_PIN0, but see below if you want BIT_0
这在 C11 6.10.3.3 The ## operator
:
中有介绍
... each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing
token is concatenated with the following preprocessing token.
The resulting token is available for further macro replacement.
现在,如果您想要一个将 BIT_
和另一个 已经计算过的宏 连接成一个标记的宏,您必须使用一些技巧来获得它在 串联之前 进行初始宏替换。
那是因为标准声明在常规宏替换之前执行串联,这就是为什么需要这种技巧的原因。你所拥有的问题:
#define PIN_0 0
#define BIT(A) BIT_##A
是 BIT(PIN0)
的 ##
扩展最初将导致 单个 令牌 BIT_PIN0
。现在,虽然这需要进一步的宏替换,但单个标记实际上 没有 宏替换,所以它保持原样。
为了解决这个问题,您必须使用间接级别强制预处理器在 ##
:
之前进行常规宏替换
#define CONCAT(x,y) x ## y
#define PIN0 0
#define BIT(A) CONCAT(BIT_,A)
上面显示的这一系列宏经历了多个阶段:
BIT(PIN0)
-> CONCAT(BIT_,PIN0)
-> CONCAT(BIT_,0)
-> BIT_0
我最近遇到这个问题,找不到解释的支持文档或数据。问题是问我的,那个人不愿意分享答案。
#define BIT(A) BIT_##A
#define PIN_0 0
"Do we get BIT_0 by using macro BIT(PIN_0)? If no make necessary corrections?"
我不知道上面问题的答案?
宏
#define BIT(A) BIT_##A
表示从两个 单独的 令牌创建一个 单个 令牌。如果不使用 ##
(令牌连接运算符),您可能会想执行以下操作之一:
#define BIT(A) BIT_A
#define BIT(A) BIT_ A
第一个问题是,因为 BIT_A
已经是单个标记,所以将 A
与传递的参数匹配的尝试不会成功,您将得到文字扩展BIT_A
无论您什么 作为参数使用:
BIT(42) -> BIT_A
第二个问题是,即使 A
是一个单独的标记,因此 将 进行替换,最终扩展将 不是是一个单一的令牌:
BIT(42) -> BIT_ 42
宏中的 ##
采用 A
指定的 值 ,并将其附加到文字 BIT_
上,形成一个标记,因此,例如,
BIT(7) -> BIT_7
BIT(PIN0) -> BIT_PIN0, but see below if you want BIT_0
这在 C11 6.10.3.3 The ## operator
:
... each instance of a ## preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token.
The resulting token is available for further macro replacement.
现在,如果您想要一个将 BIT_
和另一个 已经计算过的宏 连接成一个标记的宏,您必须使用一些技巧来获得它在 串联之前 进行初始宏替换。
那是因为标准声明在常规宏替换之前执行串联,这就是为什么需要这种技巧的原因。你所拥有的问题:
#define PIN_0 0
#define BIT(A) BIT_##A
是 BIT(PIN0)
的 ##
扩展最初将导致 单个 令牌 BIT_PIN0
。现在,虽然这需要进一步的宏替换,但单个标记实际上 没有 宏替换,所以它保持原样。
为了解决这个问题,您必须使用间接级别强制预处理器在 ##
:
#define CONCAT(x,y) x ## y
#define PIN0 0
#define BIT(A) CONCAT(BIT_,A)
上面显示的这一系列宏经历了多个阶段:
BIT(PIN0)
-> CONCAT(BIT_,PIN0)
-> CONCAT(BIT_,0)
-> BIT_0