我遇到了以下宏构造,它定义了数学算法实现的头文件中的点积。
#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并不是特别强大。
答案 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()
。我提供的例子是有效的,所以没有系统的问题,这会阻止更高的维度
我希望匹配用例。你不是在考虑不确定的,静态未知/不可预测的大量维度,不是吗?