Invoke an associative * function using C macros

* Not to be confused with anything related to associative arrays.

I know how to vectorize a function in C using macros to give results similar to the functionality of Mathematica Map (or Apply). Namely, apply the function to the argument list.

#define Apply( type, function, ...) \ { \ void *Stop = (int[]){0}; \ type **List = (type*[]){__VA_ARGS__, Stop}; \ for( int i = 0; List[i] != Stop; ++i ) \ function( List[i] ); \ } 

Then I can do something like

 #define FreeAllAtOnce(...) Apply( void, free, __VA_ARGS__ ); 

which leads to the fact that

 free( Array1 ); free( Array2 ); free( Array3 ); 

equivalently

 FreeAllAtOnce( Array1, Array2, Array3 ); 

I did not do this, I read about it in the book and have used it ever since.

My question is: Can I do something similar to associative array joining through some binary function. For example, take the GCD function. I need a function like:

 GCD_all( a, b, c, d, e ); 

This has the same effect as

 GCD( GCD( GCD( GCD( a, b ), c ), d ), e ); 

for any number of arguments.

I tried to do this and could not properly get it to work. I am also interested in the case when additional functions are passed to a function. In the most general sense, I want to do this with functions such as:

 Atype BinaryCombine( Atype a, Atype b, OtherType z, OtherType y ) 

so i have a function

 Atype BinaryCombineAll( Atype a, Atype b, Atype c, Atype d, OtherType z, OtherType y ) 

Hope this makes sense. Any ideas or help would be greatly appreciated!

Thanks.

+7
c macros c-preprocessor
source share
1 answer

To get more detailed information, a rather complicated mechanism is required (see this one), since in C:

usually no recursive macros,
 #define _NUM_ARGS2(X,X5,X4,X3,X2,X1,N,...) N #define NUM_ARGS(...) _NUM_ARGS2(0,__VA_ARGS__,5,4,3,2,1,0) // be sure to add X6,X7,... and 6,7,... to support more arguments #define GCD_OF_1(a) (a) #define GCD_OF_2(a,b) GCD(a, b) #define GCD_OF_3(a,b,...) GCD_OF_2(GCD_OF_2(a,b),__VA_ARGS__) #define GCD_OF_4(a,b,...) GCD_OF_3(GCD_OF_2(a,b),__VA_ARGS__) #define GCD_OF_5(a,b,...) GCD_OF_4(GCD_OF_2(a,b),__VA_ARGS__) // in general: // #define GCD_OF_N(a,b,...) GCD_OF_N-1(GCD_OF_2(a,b),__VA_ARGS__) #define _GCD_OF_N3(N, ...) GCD_OF_ ## N(__VA_ARGS__) #define _GCD_OF_N2(N, ...) _GCD_OF_N3(N, __VA_ARGS__) // helper macro to expand N #define GCD_all(...) _GCD_OF_N2(NUM_ARGS(__VA_ARGS__), __VA_ARGS__) int main(void) { GCD_all(a, b, c, d, e); } 

gcc -E outputs the output as:

 int main(void) { GCD(GCD(GCD(GCD(a, b), c), d), e); } 

NUM_ARGS automatically finds the number of arguments. This way you get the macro "start point" GCD_OF_N for further expansion.

+2
source share

All Articles