我正在尝试定义一个宏来生成一个包含变量的令牌名称。
基本上,我正在尝试的是:
#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,这不是我想要的。这里有什么帮助吗?还是我试图做的事情是不可能的?
我正在尝试定义一个宏来生成一个包含变量的令牌名称。
基本上,我正在尝试的是:
#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,这不是我想要的。这里有什么帮助吗?还是我试图做的事情是不可能的?
我认为您尝试做的事情是不可能的。C 宏实际上是在编译之前扩展的预处理器宏。变量port, 直到运行时才被设置。
是不可能的。C 预处理器通过处理标记来工作,它们不执行任何需要了解语言机制的解析或替换(除了涉及整数文字的基本算术,我不知道)。例如,考虑 GCC 的预处理器关于 tokenisation的文档。只有编译器会知道如何处理变量“port”。
一种解决方案是执行以下操作:
#define PxDIR(var, portnum) do { \
var = portnum; \
P##portnum##DIR |= blah; \
} while(0)
...然后...
int port;
PxDIR(port, 2);
我把它留给你,让它不像这里那样丑陋或骇人听闻(更笼统,取决于你的需要):)
...或者只是使 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;
}
你试图做的事情没有意义。
#define GLUER(x,y,z) x##y##z
#define PxDIR(x) GLUER(P,x,DIR)
int main() {
int port;
port = 2;
PxDIR(port) |= 0x01;
}
预处理器在(之前)编译时运行。因此它对变量的内容一无所知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 函数返回的空指针。