具有可变尺寸的点积的C宏

时间:2016-10-13 23:33:25

标签: c c-preprocessor

我遇到了以下宏构造,它定义了数学算法实现的头文件中的点积。

#define DIM 3
#define MULTIPLY( a, b)     ((a)*(b))
#define DOT_PRODUCT( a, b)  (     MULTIPLY( (a)[0],(b)[0]) + \
                                 MULTIPLY( (a)[1],(b)[1]) + \
                                 MULTIPLY( (a)[2],(b)[2]) )

它可能用于保持实现独立于维度。但显然,如果更改DIM,则还必须修改DOT_PRODUCT以反映该内容。

有没有办法定义DOT_PRODUCT,以便它自动尊重设置维度DIM?也许有一些(伪)递归宏魔法?我试图想出一些东西,但我的C-foo并不是特别强大。

1 个答案:

答案 0 :(得分:1)

我同意@Olaf:不要使用可以使用函数的宏。 但有时情况或欲望会超越这种想法。

预处理器有时只想在正确的位置获得正确数量的间接,所以我进行了实验,直到我得到它。我承认我无法预测,我无法详细解释,至少不是有趣的,非显而易见的部分。

#define DIM 2  
#define CONCAT(x,y,a,b) x ## y(a,b)  
#define DOT_PRODUCT_DIM(y,a,b) CONCAT(DOT_PRODUCT_,y,a,b)  
#define MULTIPLY( a, b)     ((a)*(b))  
#define DOT_PRODUCT_2( a, b)  (  MULTIPLY( (a)[0],(b)[0]) + \  
                                 MULTIPLY( (a)[1],(b)[1]) )  
#define DOT_PRODUCT_3( a, b)  (  MULTIPLY( (a)[0],(b)[0]) + \  
                                 MULTIPLY( (a)[1],(b)[1]) + \  
                                 MULTIPLY( (a)[2],(b)[2]) )  
#define DOT_PRODUCT_4( a, b)  (  MULTIPLY( (a)[0],(b)[0]) + \  
                                 MULTIPLY( (a)[1],(b)[1]) + \  
                                 MULTIPLY( (a)[2],(b)[2]) + \  
                                 MULTIPLY( (a)[3],(b)[3]) )  
#define DOT_PRODUCT(a,b)  DOT_PRODUCT_DIM(DIM,a,b)  

DOT_PRODUCT_DIM(2,a,b)  
DOT_PRODUCT_DIM(3,a,b)  
DOT_PRODUCT_DIM(4,a,b)  
DOT_PRODUCT_DIM(DIM,a,b)  
DOT_PRODUCT(a,b)  

OUTPUT(gcc -E Toy.c):

( (((a)[0])*((b)[0])) + (((a)[1])*((b)[1])) )
( (((a)[0])*((b)[0])) + (((a)[1])*((b)[1])) + (((a)[2])*((b)[2])) )
( (((a)[0])*((b)[0])) + (((a)[1])*((b)[1])) + (((a)[2])*((b)[2])) + (((a)[3])*((b)[3])) )
( (((a)[0])*((b)[0])) + (((a)[1])*((b)[1])) )
( (((a)[0])*((b)[0])) + (((a)[1])*((b)[1])) )

OUTPUT(仅在更改#define DIM 3后,仅引用最后两行输出):

( (((a)[0])*((b)[0])) + (((a)[1])*((b)[1])) + (((a)[2])*((b)[2])) )
( (((a)[0])*((b)[0])) + (((a)[1])*((b)[1])) + (((a)[2])*((b)[2])) )

OUTPUT(仅在更改#define DIM 4后,仅引用最后两行输出):

( (((a)[0])*((b)[0])) + (((a)[1])*((b)[1])) + (((a)[2])*((b)[2])) + (((a)[3])*((b)[3])) )
( (((a)[0])*((b)[0])) + (((a)[1])*((b)[1])) + (((a)[2])*((b)[2])) + (((a)[3])*((b)[3])) )  

OUTPUT(仅在更改#define DIM 5后,仅引用最后两行输出):

DOT_PRODUCT_5(a,b)
DOT_PRODUCT_5(a,b)  

当然,必须定义中间宏DOT_PRODUCT_number()。我提供的例子是有效的,所以没有系统的问题,这会阻止更高的维度 我希望匹配用例。你不是在考虑不确定的,静态未知/不可预测的大量维度,不是吗?