我正在尝试定义一个宏来生成包含变量的令牌名称。
基本上,我正在尝试的是:
#define GLUER(x,y,z) x##y##z
#define PxDIR(x) GLUER(P,x,DIR)
int main() {
int port;
port = 2;
PxDIR(port) |= 0x01;
}
我希望在上面的语句中生成令牌P2DIR,但是根据我的编译器输出,它正在生成令牌PportDIR,这不是我想要的。这里有什么帮助?或者我正在尝试做什么不可能?
答案 0 :(得分:9)
我不认为你想做的事情是可能的。 C宏实际上是在编译之前扩展的预处理器宏。变量port
在运行时才会设置。
答案 1 :(得分:6)
这是不可能的。 C预处理器通过处理令牌来工作,并且他们不做任何需要知道语言机制的解决方案或替换(除了涉及整数文字的基本算术,在我的头顶之外)。例如,考虑GCC预处理器regarding tokenisation的文档。只有编译器才知道如何处理变量“port。”
一种解决方案是做类似的事情:
#define PxDIR(var, portnum) do { \
var = portnum; \
P##portnum##DIR |= blah; \
} while(0)
......以后......
int port;
PxDIR(port, 2);
我留给你的是为了让它不像在这里那样丑陋或笨拙(更一般,取决于你需要的东西):)
答案 2 :(得分:3)
...或者只是让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;
}
答案 3 :(得分:0)
您尝试做的事情没有意义。
#define GLUER(x,y,z) x##y##z
#define PxDIR(x) GLUER(P,x,DIR)
int main() {
int port;
port = 2;
PxDIR(port) |= 0x01;
}
preprocesser在(编译时)之前运行。因此,它无法了解变量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函数返回的空指针。