涉及变量的 C 宏标记串联 - 可能吗?

发布于 2024-09-17 16:46:11 字数 291 浏览 9 评论 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;
}

我希望在上面的语句中生成令牌 P2DIR,但根据我的编译器输出,它生成令牌 PportDIR,这不是我想要的。这里有什么帮助吗?或者我正在尝试做的事情是不可能的?

I'm trying to define a macro to generate a token name, containing a variable.

Basically, what I'm trying is this:

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

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

I'm hoping to generate the token P2DIR in the above statement, but according to my compiler output, it's generating the token PportDIR, which is NOT what I wanted. Any help here? Or is what I'm attempting to do impossible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

青衫负雪 2024-09-24 16:46:11

我认为你想做的事情是不可能的。 C 宏实际上是在编译之前展开的预处理器宏。变量 port 直到运行时才会设置。

I don't think what you're trying to do is possible. C macros are really preprocessor macros that are expanded before compilation. The variable port, doesn't get set until runtime.

此生挚爱伱 2024-09-24 16:46:11

这是不可能的。 C 预处理器通过处理标记来工作,并且它们不执行任何需要了解语言机制的解析或替换(除了涉及整数文字的基本算术,这是我无法想象的)。例如,请考虑 GCC 预处理器关于标记化的文档。只有编译器知道如何处理变量“port”。

一种解决方案是执行以下操作:

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

...然后...

int port;
PxDIR(port, 2);

我将其留给您,以使它不像这里那样丑陋或hacky(并且更一般,取决于您需要什么):)

It is impossible. C preprocessors work by processing tokens, and they do not do any resolution or substitution that would require knowledge of the mechanics of the language (except basic arithmetic involving integer literals, off the top of my head). Consider, for example, the docs for GCC's preprocessor regarding tokenisation. Only a compiler will know what to do with the variable "port."

One solution is to do something like:

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

...and later...

int port;
PxDIR(port, 2);

I leave it to you to make this not as ugly or hacky as it is here (and more general, depending on what you need) :)

无需解释 2024-09-24 16:46:11

...或者只是让 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;
}

... or just make PORT also a macro:

#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;
}
笨死的猪 2024-09-24 16:46:11

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

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

What you're trying to do doesn't make sense.

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

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

The preprocesser is run at (before) compile time. Therefore it can't know anything about the contents of the variable port. The preprocessor requires that any values passed as arguments to macros be constants. For example, you could do the following:

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

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

Otherwise, if you want to be able to pass a variable to this macro really the only way is to make sure the code to do so is explicitly generated:

#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;
}

In this way we make sure there is code for any port from 0 to 3 to be accessed. Also, now we have to watch out for null pointers getting returned from the get_port_pointer function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文