RedArrow
RedArrow

Reputation: 638

C macro for passing multiple variable arguments

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.

Upvotes: 4

Views: 8178

Answers (3)

M Oehm
M Oehm

Reputation: 29126

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.)

Upvotes: 5

Elad Hazan
Elad Hazan

Reputation: 331

try - #define WRAP_MY_FUNCTION(x,y) (myfunction(x,y))

and call the define as follows:

WRAP_MY_FUNCTION(x,y);

which x is: int x[] = { 1,1,1,0 };

and y is : char y[] = { 2,2,0 };

Upvotes: 2

Florian Weimer
Florian Weimer

Reputation: 33747

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.

Upvotes: 2

Related Questions