我最近遇到过这个问题,无法找到支持文档或数据进行解释。这个问题被问到我,而且这个人不愿意分享答案。
#define BIT(A) BIT_##A
#define PIN_0 0
“我们是否通过使用宏BIT(PIN_0)获得BIT_0?如果没有进行必要的更正?”
我不知道上述问题的答案?
答案 0 :(得分:10)
宏
#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_
,形成一个令牌,例如,< / p>
BIT(7) -> BIT_7
BIT(PIN0) -> BIT_PIN0, but see below if you want BIT_0
这涵盖在C11 6.10.3.3 The ## operator
:
...删除替换列表中的##预处理标记的每个实例(不是来自参数)并进行前面的预处理 token与以下预处理标记连接。
生成的令牌可用于进一步的宏替换。
现在,如果你想要一个将BIT_
和另一个已经评估的宏连接在一起的宏到一个令牌中,你必须使用一些技巧来让它做初始化在串联之前宏替换。
那是因为标准规定在常规宏替换之前执行串联,这就是需要这种技巧的原因。你有什么问题:
#define PIN_0 0
#define BIT(A) BIT_##A
##
的{{1}}扩展最初会产生单标记BIT(PIN0)
。现在,虽然这可以进行进一步的宏替换,但是单个令牌实际上没有宏替换,所以它保持原样。
要解决这个问题,你必须使用间接级别强制预处理器在BIT_PIN0
之前进行常规宏替换:
##
上面显示的这一系列宏经历了许多阶段:
#define CONCAT(x,y) x ## y
#define PIN0 0
#define BIT(A) CONCAT(BIT_,A)