预处理器指令,用于将符号与C中的变量值连接

时间:2013-01-07 12:14:18

标签: c macros c-preprocessor avr-gcc

这是在 C 中完成符号连接的方式。

#define conc(a,b) a ## b

例如:

conc(hello,World)会生成符号helloWorld

我需要知道的是有点不同。假设有一个变量n,它包含一些整数。现在我需要通过将另一个符号与 n连接来创建符号。

例如:

n = 2
我需要定义一些function(...),以便function(symbol,n)提供symbol1(不是symboln),当n = 3时,function(symbol,n)会提供symbol3等等......

我该如何定义类似的内容?


这是我真正想要实现的目标。首先,这将用于AtmelStudio编程atmega微控制器。那里有4个USART模块,因此是一组独立的寄存器,只根据模块的数量改变名称。

例如,四个模块中的四个波特率寄存器是UBRR0LUBRR1LUBRR2LUBRR3L。 (还有几个,见下文)。

enter image description here

我需要编写一个函数来通过设置相关寄存器的值来初始化给定模块。由于寄存器名称仅因模块编号而异,如果我可以按照本文中的要求定义一些预处理器指令,我可以用一些符号编写一个表示寄存器名称的函数,因此符号将带有相关的寄存器名称和事情会好起来的。

例如:

如果我可以定义conc(a,b)来做我需要的,一个简单的函数

void init(int no){
    conc(UBRR,no) = 0xF0;
}

将能够用来代表以下所有内容;

UBRR0 = 0xF0;
UBRR1 = 0xF0;
UBRR2 = 0xF0;
UBRR3 = 0xF0;

如果这是不可能实现的,我唯一知道的就是重写四个独立的功能。但希望有更好的选择..

4 个答案:

答案 0 :(得分:5)

预处理器将在编译之前对您的代码进行操作。显然在运行时间之前。所以没有预处理器指令可以解决你的目的。

最接近的匹配是使用如下的开关案例:

switch(n){
case 0: ptr=&symbol0; break;
case 1: ptr=&symbol1; break;
case 2: ptr=&symbol2; break;
case 3: ptr=&symbol3; break;
case 4: ptr=&symbol4; break;
case 5: ptr=&symbol5; break;
//etc... needs to be filled manually.
}

&安培;然后在*ptr ...

上进行操作

此外,如果您的变量名称将是顺序的,为什么不具有数组,名称为符号& symbol0已更改为symbol[0]

编辑: 现在看到问题中的编辑。 您可以如上所示使用switch case,或者创建一个指针数组,这些指针将保留UBRR0LUBRR0L等。&然后将它与索引一起使用。据我所知,它们只是寄存器和放大器。将出现在固定地址。

答案 1 :(得分:4)

您无法使用C预处理器执行此操作,因为变量的值是在运行时确定的。但您可以使用snprintf()根据运行时的数字构建字符串。

答案 2 :(得分:2)

在我看来,寄存器(例如RXC0,RXC1,RXC2等)是等距的。如果这个假设为真,你可以计算下面寄存器的地址(只需用寄存器的类型替换rint):

rint *
register_address(rint *first, rint *second, unsigned int n)
{
    size_t diff = second - first;

    return first + diff * n;
}

您的init()功能将如下所示:

void
init(int no)
{
    *register_address(&UBRR0, &UBRR1, no) = 0xF0;
}

这个函数调用可以通过宏简化/隐藏:

#define register_value(name, no) *register_address(&conc(name, 0), &conc(name, 1), no)

所以你可以写:

void
init(int no)
{
    register_value(UBRR, no) = 0xF0;
}

此代码未经测试,我不确定它是否真的有效。如果它可以工作并且您将要使用它,我将通过静态断言来测试该假设。

答案 3 :(得分:0)

真正的窍门如下:

#define TIMER_0     0
#define TIMER_1     1
#define TIMER_2     2

#define _SET_TIMER_NORMAL_MODE(val)        TCCR ## val &= ~(1 << WGM ## val ## 0)
#define SET_TIMER_NORMAL_MODE(instance)     _SET_TIMER_NORMAL_MODE(instance)

现在我们可以将其用作:

SET_TIMER_NORMAL_MODE(TIMER_0)

扩展为:

 _SET_TIMER_NORMAL_MODE(0)

此外,它扩展为:

TCCR0 &= ~(1 << WGM00)