C宏令牌连接涉及变量 - 是否可能?

时间:2010-09-03 04:22:37

标签: c concatenation token c-preprocessor stringification

我正在尝试定义一个宏来生成包含变量的令牌名称。

基本上,我正在尝试的是:

#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,这不是我想要的。这里有什么帮助?或者我正在尝试做什么不可能?

4 个答案:

答案 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函数返回的空指针。