涉及变量的C宏令牌串联 - 有可能吗?

涉及变量的C宏令牌串联 - 有可能吗?

问题描述:

我想要定义一个宏来生成一个包含变量的标记名称。涉及变量的C宏令牌串联 - 有可能吗?

基本上,我想是这样的:

​​

我希望能产生上述声明令牌P2DIR,但根据我的编译器的输出,它生成令牌PportDIR,这是不是我想要的。这里有帮助吗?或者是我试图做不可能的事情?

+0

你打算做'#define port 2'吗? – Gabe 2010-09-03 04:40:16

我不认为你想要做什么是可能的。 C宏是在编译之前展开的预处理宏。变量port,直到运行时才会被设置。

+0

谢谢,这正是我的想法。它已经有一段时间了,因为我已经完成了直行C. – gatesphere 2010-09-03 04:50:22

这是不可能的。 C预处理器通过处理标记来工作,并且它们不做任何需要知道该语言机制的解析或替换(除了涉及整数文字的基本算术,不在我头顶)。例如,考虑GCC预处理器regarding tokenisation的文档。只有编译器会知道如何处理变量“端口”。

一种解决办法是做这样的事情:

#define PxDIR(var, portnum) do { \ 
    var = portnum; \ 
    P##portnum##DIR |= blah; \ 
} while(0) 

......后来......

int port; 
PxDIR(port, 2); 

我让你做这个不丑或哈克,因为它是这里(和更普遍的,这取决于你的需要):)

+0

谢谢。我正在研究它作为一种减少嵌入式项目中代码膨胀的方法,但它看起来好像不可能使用变量来解决这个问题。呃,好吧。再次感谢! – gatesphere 2010-09-03 04:52:27

+0

@ user438605事实上 - 尽管您可能想要查看[X Macro Idiom](http://www.drdobbs.com/184401387)以重复生成代码。 – detly 2010-09-03 08:39:16

...或者只是做PORT也是宏:

#define PORT 2 
#define GLUER(x,y,z) x##y##z 
#define PxDIR(x) GLUER(P,x,DIR) 

int main() { 
    PxDIR(PORT) |= 0x01; 
    return 0; 
} 

你试图做的事情没有意义。

​​

预处理器在编译时(之前)运行。因此它无法知道变量port的内容。预处理器要求任何作为宏参数传递的值都是常量。例如,你可以做到以下几点:

#define GLUER(x,y,z) x##y##z 
#define PxDIR(x) GLUER(P,x,DIR) 

int main() { 
    PxDIR(2) |= 0x01; //setup port 2 
} 

否则,如果你希望能够给一个变量传递给这个宏真的是唯一的办法就是确保明确生成的代码可以这样做:

#define GLUER(x,y,z) x##y##z 
#define PxDIR(x) GLUER(P,x,DIR) 

uint16_t* get_port_pointer(uint8_t port_id) { 
    if (port == 0) { 
    return &PxDIR(0); 
    } else if (port == 1) { 
    return &PxDIR(1); 
    } else if (port == 2) { 
    return &PxDIR(2); 
    } else if (port == 3) { 
    return &PxDIR(3); 
    } else { 
    return &0; 
    } 
} 

int main() { 
    int port; 
    port = 2; 

    *(get_port_pointer(port)) |= 0x01; 
} 

通过这种方式,我们确保存在从0到3的任何端口被访问的代码。另外,现在我们必须注意从get_port_pointer函数返回的空指针。