简体   繁体   中英

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

Consider the macro

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

I would like to define the arguments a,b,c,d in another macro. So I have done this:

#define DEBUG_HOST_IP4 192, 168, 0, 123

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

The first call to IP4_ADDR compiles succesfully, while the second one fails with

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

Is there a way to make DEBUG_HOST_IP4 expand properly, so the IP4_ADDR macro can work as intended?

EDIT: The IP4_ADDR macro comes from a third-party library, which I would rather not touch, and risk breaking somebody else's code. Of course, implementing my own version is an option.

In this case, you can make your outer macro a varargs macro:

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

The macro invocation must have the correct number of arguments. The inner macro invocation works because arguments are expanded before the body is rescanned.

The varargs syntax allows you to either supply the four arguments or use a macro which expands to them.

If you don't want to alter the definition of IP_ADDR , you invoke it indirectly through a wrapper macro:

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

Try to define like this:

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

DEGUB_HOST_IP4 will be replaced only in second part. So when you passed it as parameter, it was replaced only to a, and b, c, d was ignored

If you can't alter IP4_ADDR, this is still pretty easy; just wrap it:

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

During the translation (which just moves all of the arguments over, whatever they are), any macros will expand. Then just use your wrapped version in the code.

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

And you should be good to go.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM