简体   繁体   English

用C宏调用Associative *函数

[英]Calling an Associative* Function with C Macros

*Not to be confused with having anything to do with Associative Arrays. *不要与关联数组有关。

I know how to vectorize a function in C with macros to give results similar to the Mathematica's Map (or Apply) functionality. 我知道如何使用宏对C函数进行矢量化处理,以提供类似于Mathematica的Map(或Apply)功能的结果。 Namely apply a function to a list of arguments. 即将函数应用于参数列表。

#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] );                         \
}                     

I can then do something like 然后我可以做类似的事情

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

which has the effect that 效果是

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

is equivalent to 相当于

FreeAllAtOnce( Array1, Array2, Array3 );

I didn't make that up, I read about it in a book and have used it heavily since. 我没有化妆,我在书中读到它,从那以后就大量使用了。

My question is: Can I do something similar to associatively combine an array via some binary function. 我的问题是:我可以做一些类似于通过一些二进制函数联合组合数组的事情。 For example take the GCD function. 例如,使用GCD功能。 I want a function like: 我想要一个像这样的函数:

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

That has the same effect as 效果与

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

for any number of arguments. 对于任何数量的参数。

I've tried to do this and have not been able to properly make it work. 我已尝试执行此操作,但无法使其正常工作。 I'm also interested in the case where there may be additional parameters passed to the function. 对于可能还有其他参数传递给函数的情况,我也很感兴趣。 In the most generic sense I'm looking to do this with functions like: 从最一般的意义上讲,我希望通过类似的功能来做到这一点:

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

so that I have a function 这样我就可以了

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

I hope that makes sense. 我希望这是有道理的。 Any ideas or help would be very appreciated! 任何想法或帮助将不胜感激!

Thanks. 谢谢。

This requires rather tricky machinery (see this answer for more details), since you cannot normally have recursive macros in C: 这需要相当复杂的机制(有关更多详细信息,请参见此答案 ),因为通常无法在C中使用递归宏:

#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);
}

The gcc -E produces output as: gcc -E产生的输出为:

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

The NUM_ARGS automagically finds the number of arguments. NUM_ARGS自动查找参数数量。 This way you obtain the "starting point" macro GCD_OF_N for futher expanding. 这样,您将获得“起点”宏GCD_OF_N以进行进一步扩展。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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