用C中的宏替换带有常量字符串参数的函数

时间:2014-07-11 10:12:28

标签: c macros

在我工作的项目中,我们有一些实用函数,它们有两个参数,一个是要写的地址,第二个是要写的值。

让我们使用一个简单的例子:

enum {
ADDR1 = 0x1000,
ADDR2 = 0x1500,
....
};

void Hardware_write_reg(ADDR,val)
{
switch ADDR {
case ADDR1 : abc.x = val; break;
case ADDR2 : abc.f = val; break;
.....
.....
}

在整个项目中,使用不同的ADDR和值作为参数,在许多文件中多次调用此函数“Hardware_write_reg”。

现在,我需要删除对“Hardware_write_reg”的调用,并直接写入struct成员。 例如,下面的Function1()需要更改

改变之前:

Function1()
{
Hardware_write_reg(ADDR1,val1);
Hardware_write_reg(ADDR2,val4);
Hardware_write_reg(ADDR7,val6);
.....
}`

更改后:

Function1()
{
abc.x = val1;
abc.f = val4;
abc.s = val6;
.....
}

我无法手动执行此操作,因为在多个文件中多次调用Hardware_write_reg()。

我尝试使用C Macro,就像这样;但无法获得预期的结果

#define Hardware_write_reg(ADDR1,A) do{\
abc.x = ((A));\
}while(0)

#define Hardware_write_reg(ADDR2,B) do{\
abc.f = ((B));\
}while(0)

基本上,我想替换(在编译时)

1) Hardware_write_reg(ADDR1,val1); function call to abc.x = val1; with a macro
2) Hardware_write_reg(ADDR2,val2); function call to abc.f = val2; with a macro 
3)....

C-Guru的任何帮助都将不胜感激!

4 个答案:

答案 0 :(得分:2)

你可以定义一堆宏

#define target_ADDR1 abc.x
#define target_ADDR2 abc.f
#define CONCAT2(a, b) a##b
#define Hardware_write_reg(ADDR,val) CONCAT2(target_,ADDR) = val

这样

Hardware_write_reg(ADDR1,42);

替换为

target_ADDR1 = 42;

因此

abc.x = 42;

就是你得到的。

免责声明:我还没有对它进行测试,但我确信这应该可行。

答案 1 :(得分:1)

而不是以编程方式解决这个问题,您可以尝试使用正则表达式替换,这包括在今天的大多数文本编辑器中。但这里的问题是对于开关中的每个案例,你必须稍微修改正则表达式。并且您的代码中不应该包含任何其他 Hardware_write_reg

搜索

  

Hardware_write_reg(ADDR1,缬氨酸([0-9] +));

替换为

  

abc.x = val \ 1;

此外,如果您有许多情况,可以使用小脚本生成正则表达式和替换。

答案 2 :(得分:0)

我能想象的唯一适用于这种情况的是将赋值操作放入switch语句

#define Hardware_write_reg(ADDR,A) do{\
    switch((ADDR)) { \
    case ADDR1: abc.x = ((A));\
    case ADDR2: abc.f = ((A));\
    ...
    } \
} while(0)

答案 3 :(得分:0)

由于C宏在编译期间无法猜测ADDR的值,因此无法为每个ADDR设置适当的结构成员。

如您所愿,将函数调用替换为实际赋值语句。所以看起来你能做到的唯一方法就是在代码中查找/替换。为此,您可以编写正则表达式并使用它来查找替换。例如,对于ADDR1:

找到正则表达式:

(Hardware_write_reg)[(](ADDR1)[,]([\w]*)[)];

并将其替换为:

abc.x = $3;

上述正则表达式在eclipse中兼容