如何将 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 );
你应该可以开始了。
考虑宏
#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 );
你应该可以开始了。