Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C macro for passing multiple variable arguments

Tags:

c

I have a function takes parameters as arrays. I also give array values with anonymous array initialization such as

        myfunction(char[]{1,1,1,0},int[]{2,2,0});

myfunction scans each array till find zero element. Different size of arrays acceptable as you put zero to the end of array.

I need a C macro to wrap that myfunction.

        #define WRAP_MY_FUNCTION(X,Y)  myfunction(int[]X,char[]Y)

And wish to use such as :

       WRAP_MY_FUNCTION({1,1,1,0},{2,2,0}) 

to obtain my function :

       myfunction(char[]{1,1,1,0},int[]{2,2,0})

But compiler says that you enter 7 parameters but expected 2 parameters. Then i tried variadic arguments as below:

       #define WRAP_MY_FUNCTION(...)  myfunction(int[]__VA_ARGS__,char[]__VAR_ARGS__) 

but as is seen above in this method it is not possible to make distinct VA_ARGS expressions for each array initialization.

Is it possible to realize such an implementation with C macro usage ?

NOTE : my primary intention in this macro usage was for anonymous array initialization, exactly i do NOT want to define structs such as int x[4]={1,1,1,0}; int y[3]={2,2,0} .. etc as is seen from my question. I wish to write macro as below

              WRAP_MY_FUNCTION({1,1,1,0},{2,2,0})

M Oehm and Florian Weimer thanks for your answers. They are acceptable, but for now i am willing to listen new answers also. In especially as noted M Oehm , my aim was to hide 0 at the end of the arrays.

like image 320
RedArrow Avatar asked Oct 21 '25 22:10

RedArrow


2 Answers

The preprocessor cannot detect the curly braces in the arguments, but it can detect nested parentheses. Redesign your macro to:

WRAPPER((1, 1, 1), (2, 2, 0));

The following definitions:

#define IARG(...) int[]{__VA_ARGS__, 0}
#define CARG(...) char[]{__VA_ARGS__, 0}
#define WRAPPER(CHARS, INTS) funct(CARG CHARS, IARG INTS)

will then expand to:

funct(char[]{1, 1, 1, 0}, int[]{2, 2, 0, 0});

The parentheses in the macro invocation will be treated as arguments to CARG and IARG. The substitution process is:

WRAPPER((1, 1, 1), (2, 2, 0));
funct(CARG (1, 1, 1), IARG (2, 2, 0));
funct(char[]{1, 1, 1, 0}, int[]{2, 2, 0, 0});

I'm not sure whether that macro buys you much, though. The nested parentheses syntax is unintuitive and you might be better off to use the verbatim syntax, especially when you revisit your code a few months later. (I've made the macro terminate the array with a zero automatically, so that there's at least some benefit to using it.)

like image 102
M Oehm Avatar answered Oct 23 '25 12:10

M Oehm


Commas in macro arguments are treated as macro argument separators unless they are nested in parentheses. Something like this would work:

void my_function(int[], char[]);
#define WRAP_MY_FUNCTION(x, y) my_function((int[]) x, (char[]) y)
#define ARG(...) { __VA_ARGS__ }

WRAP_MY_FUNCTION(ARG(1, 2, 3), ARG(4, 5, 6));

There does not seem to be a way out of the additional macro invocation because

(int[]) ({1, 2, 3})

is not syntactically valid (and it has been reused as a GNU extension), and

(int[]) {(1, 2, 3)}

has a different meaning because it invokes the comma operator and creates a one element array.

like image 22
Florian Weimer Avatar answered Oct 23 '25 12:10

Florian Weimer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!