如何将 C 宏的一些参数定义为另一个宏?

How can I define some arguments of a C macro as another macro?

考虑宏

#define IP4_ADDR(ipaddr, a,b,c,d)  (ipaddr)->addr = PP_HTONL(LWIP_MAKEU32(a,b,c,d))

我想在另一个宏中定义参数 a,b,c,d。所以我这样做了:

#define DEBUG_HOST_IP4 192, 168, 0, 123

IP4_ADDR(&debug_host, 192, 168, 0, 123 );
IP4_ADDR(&debug_host, DEBUG_HOST_IP4 );

第一次调用 IP4_ADDR 编译成功,而第二次调用失败

error: macro "IP4_ADDR" requires 5 arguments, but only 2 given
IP4_ADDR(&debug_host, DEBUG_HOST_IP4 );

有没有办法使 DEBUG_HOST_IP4 正确扩展,以便 IP4_ADDR 宏可以按预期工作?

编辑:IP4_ADDR 宏来自第三方库,我宁愿不碰它,以免破坏别人的代码。当然,实现我自己的版本是一种选择。

尝试这样定义:

#define IP4_ADDR(ipaddr, HOST)  (ipaddr)->addr = PP_HTONL(LWIP_MAKEU32(HOST))

DEGUB_HOST_IP4 只会在第二部分被替换。所以当你把它作为参数传递时,它只被替换为a,而b,c,d被忽略了

在这种情况下,您可以将外部宏设为可变参数宏:

#define IP4_ADDR(ipaddr, ...)  (ipaddr)->addr = PP_HTONL(LWIP_MAKEU32(__VA_ARGS__))

宏调用必须有正确数量的参数。内部宏调用有效,因为在重新扫描正文之前扩展了参数。

可变参数语法允许您提供四个参数或使用扩展到它们的宏。

如果您不想更改 IP_ADDR 的定义,您可以通过包装器宏间接调用它:

#define CALL(macro, __VA_ARGS__) macro(...)
// ...
CALL(IP4_ADDR, &debug_host, DEBUG_HOST_IP4 );

如果你不会改变IP4_ADDR,这还是很容易的;把它包起来:

#define MY_IP4_ADDR(...) IP4_ADDR(__VA_ARGS__)

在翻译过程中(只是移动所有参数,无论它们是什么),任何宏都会展开。然后只需在代码中使用您的包装版本。

  MY_IP4_ADDR(&debug_host, 192, 168, 0, 123 );
  MY_IP4_ADDR(&debug_host, DEBUG_HOST_IP4 );

你应该可以开始了。