我正在尝试为我目前编程的微控制器制作一段更通用的代码。
我想要的是一个特定的宏,通过串联从其他令牌形成。问题是其中一个令牌被定义为特定的存储器地址(即寄存器),因此“垃圾”在中途被替换。以下代码段说明了问题:
#include <stdio.h>
#include <stdint.h>
// The actual final token that I want (because I want the value of 10)
#define I_DRINK_BEER 10
// This line is the problematic line!
// It us defined in the microcontroller-specific header
// If this line is not defined, it works perfectly as desired.
#define DRINK (*(uint32_t*) (0x8000))
#define ACTION DRINK
#define INDIRECT(who,action,what) who ## action ## what
#define TOKEN_PASTE(who,action,what) INDIRECT(who,action,what)
#define CONSUMPTION(who,what) TOKEN_PASTE(who,ACTION,what)
int main(void)
{
printf("Value = %d\n", CONSUMPTION(I_,_BEER));
return 0;
}
如果注释掉“#define DRINK ...”行,程序将根据需要编译并执行:
damien@damien-desktop:~$ gcc -o test test_macro_expansion.c
damien@damien-desktop:~$ ./test
Value = 10
但是包含违规行代替了使预处理器抱怨的完整地址:
test_macro_expansion.c: In function ‘main’:
test_macro_expansion.c:21:1: error: pasting "I_" and "(" does not give a valid preprocessing token
test_macro_expansion.c:21:1: error: pasting ")" and "_BEER" does not give a valid preprocessing token
test_macro_expansion.c:21:28: error: expected ‘)’ before ‘_BEER’
有没有办法告诉预处理器不要再替换特定的令牌?
为什么?
在此之前看起来有点深奥,我有一个特定功能的计时器,分配给一个项目中的计时器/计数器“TCC0”和另一个项目中的“TCD1”。它恰好被定义为每个定时器的寄存器块的基地址。所以,我有我的配置标题:
#define PERIPHERAL_TIMER TCC0
其中,在main中运行良好,因为可以很容易地引用计时器的寄存器,例如:
value = PERIPHERAL_TIMER.CCA;
在工具链的深处,定义了TCC0:
#define TCC0 (*(TC0_t *) 0x0800) /* Timer/Counter C0 */
问题是我有其他定义的宏,其中有TCC0)作为我在其他地方需要的名称的一部分,例如:
// Note the TCC0 in the function argument!
EventSystem_SetEventSource(EVSYS_CHMUX_TCC0_OVF_gc);
因此,我想定义符号
// Conceptually what I want!
#define EVENT_SOURCE(timer) EVSYS_CHMUX_ ## timer ## _OVF_gc
// The "PERIPHERAL_TIMER" gets expanded to the address, not the token that I want
#define PERIPHERAL_EVENT EVENT_SOURCE(PERIPHERAL_TIMER)
我希望这能解清为什么我在问这个问题。
答案 0 :(得分:0)
#define DRINK (*(uint32_t) (0x8000))
。
这一行有一个错误,就像UNDEFINED Symbol uint一样。
答案 1 :(得分:0)
嗯,解决这个问题的最简单,最简单的解决方法是:
// It was this...
// #define PERIPHERAL_TIMER TCC0
// And is now this
#define PERIPHERAL_TIMER_SUFFIX C0
因此可以很容易地定义宏:
// Conceptually what I want - modified, but be sure to use
// indirect substitution as required.
#define EVENT_SOURCE(timer) EVSYS_CHMUX_TC ## timer ## _OVF_gc
仍然可以定义PERIPHERAL_TIMER以进行直接寄存器访问:
// Don't forget, you'll need to use indirect substitution
#define PERIPHERAL_TIMER TC ## PERIPHERAL_TIMER_SUFFIX
// Registers can still be access as:
value = PERIPHERAL_TIMER.CCA;
注意:本文中的间接替换是指this answer中的技术。