C preproc:粘贴有效令牌和令牌值 [英] C preproc: pasting valid token and value of a token
问题描述
我正在使用 STM32F1 微控制器,为此提供了一个标头,用于定义寄存器的位掩码和值,如下所示:
I am working with an STM32F1 microcontroller, for which a header is provided that defines bit masks and values for registers as follows:
#define RCC_CFGR_PLLMULL //Mask of PLL multiplier setting bits
#define RCC_CFGR_PLLMULL1 //Value of PLL multiplier bits for PLL x1
#define RCC_CFGR_PLLMULL2 //Value of PLL multiplier bits for PLL x2
#define RCC_CFGR_PLLMULL3 //Value of PLL multiplier bits for PLL x3
等等等等
我想要做的是将我的 PLL 乘法器定义为一个整数,以便我可以使用它来导出时钟值 - 即 PLLCLK = IN_CLK * PLL_MULT
- 并将该值粘贴到 RCC_CFGR_PLLMULL
获取正确的设置位.我通常为此使用的宏如下:
What I want to do is define my PLL multiplier as an integer so I can use it to derive the clock value - ie PLLCLK = IN_CLK * PLL_MULT
- and paste the value onto RCC_CFGR_PLLMULL
to obtain the correct setting bits. The macros I would normally use for this are as follows:
#define APPEND_VAL_HELPER(A, B) A##B
#define APPEND_VAL(A, B) APPEND_VAL_HELPER(A,B)
然后,如果我将 SOME_NUM 定义为 123:
Then if I define SOME_NUM as, say, 123:
#define FOO APPEND_VAL(BAR, SOME_NUM)
结果 FOO
定义为 BAR123
.通常这是有效的.问题是:在这种情况下,RCC_CFGR_PLLMULL
在粘贴之前是一个有效的令牌.这导致它在 APPEND_VAL
的调用中扩展,我得到类似 ((uint32_t)0x003C0000)123
的东西.我不知道如何在不扩展 A
的情况下让 B
扩展,至少在 GCC 中是这样.有解决方法,但我正在寻找一个干净的解决方案.存在吗?
Results in the FOO
defining as BAR123
. Normally this works. Here's the problem: in this case, RCC_CFGR_PLLMULL
is a valid token before being pasted. This results in it expanding in the invocation of APPEND_VAL
and I get something like ((uint32_t)0x003C0000)123
. I can't figure out how to get B
to expand without also expanding A
, at least in GCC. There are workarounds to this but I'm looking for a clean solution. Does it exist?
推荐答案
我不确定您认为什么是干净"的解决方案,但这对我有用,而且看起来还不错:
I'm not sure what you would consider a "clean" solution, but this works for me and doesn't seem too bad:
/* target header */
#define RCC_CFGR_PLLMULL 0x003C
#define RCC_CFGR_PLLMULL1 0x0003
/* pasting macros */
#define APPEND_VAL_HELPER(A, B) A ## B
#define APPEND_VAL(A, B) APPEND_VAL_HELPER(A, B)
#define RCC_CFGR(T, N) APPEND_VAL(RCC_CFGR_, APPEND_VAL(T, N))
例如,您将其用作
#define FOO RCC_CFGR(PLLMUL, 1)
你也可以
#define BAR RCC_CFGR(PLLMUL, )
将BAR
定义为RCC_CFGR_PLLMUL
(无尾).
显然,这是特定于可能的目标宏的子集,但它可以完成工作并且读取干净.据我所知,没有办法编写一个完全通用的标记粘贴宏——那些最通用的宏会遇到诸如您所描述的问题.
Obviously, this is specific to a subset of possible target macros, but it does the job and reads cleanly. To the best of my knowledge there is no way to write a fully general token-pasting macro -- those that are most general suffer from issues such as the one you described.
这篇关于C preproc:粘贴有效令牌和令牌值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!