我有一个ansi C函数,可以根据模式对数组中的值求和。类似的东西:
long sum_all_according_to_pattern(int n, int *values, int *pattern)
{
long sum = 0;
int i = 0;
for(;i<n;i++){
if(pattern[i])
sum+=values[i];
}
return sum;
}
我们说我有一套模式,例如:
模式1:1,1,1,1
模式2:1,1,0,0
模式3:1,0,0,1
我需要为每个模式生成一个特定的代码,没有循环和if。对于以前的模式,它将是:
long sum_according_to_pattern_1(int *values)
{
return values[0]+values[1]+values[2]+values[3];
}
long sum_according_to_pattern_2(int *values)
{
return values[0]+values[1];
}
long sum_according_to_pattern_3(int *values)
{
return values[0]+values[3];
}
甚至
long sum_according_to_pattern_1(int *values)
{
long sum = 0;
sum+=values[0];
sum+=values[1];
sum+=values[2];
sum+=values[3];
return sum;
}
long sum_according_to_pattern_2(int *values)
{
long sum = 0;
sum+=values[0];
sum+=values[1];
return sum;
}
long sum_according_to_pattern_3(int *values)
{
long sum = 0;
sum+=values[0];
sum+=values[3];
return sum;
}
现在,假设这样的模式可以比仅仅4个元素大得多。另外,假设我不仅仅是这3种模式。
我的问题是:有一些方法可以使用ansi C构造实现这一目标吗?当我试图保持所有内容时,我不想编写脚本来为我生成代码。我需要的是使用类似位图宏的方式指定模式,然后在编译期间生成函数。
答案 0 :(得分:2)
我会这样做的方法是使用一个宏来定义你想要的所有模式,并结合其他宏来定义你需要的函数或其他信息。所以你会有类似的东西:
#define FUNCTION_PATTERNS(M) \
M(1, 0xf) \
M(2, 0x3) \
M(3, 0x9)
#define DEFINE_SUM_FUNCTION(NUM, PATTERN) \
long sum_according_to_pattern_##NUM(int *values) { \
long sum = 0; \
for (int i = 0; 1UL << i <= PATTERN; i++) \
if (PATTERN & (1UL << i)) sum += values[i]; \
}
#define SUM_FUNCTION_NAME(NUM, PATTERN) sum_according_to_pattern_##NUM
现在您可以轻松声明所有函数并构建一个指向它们的指针表:
FUNCTION_PATTERNS(DEFINE_SUM_FUNCTION)
long (*sum_functions[])(int *) = { FUNCTION_PATTERNS(SUM_FUNCTION_NAME) };
如果需要,可以在DEFINE_SUM_FUNCTION
宏中手动展开循环,或者依靠C编译器为您执行此操作,可能使用适当的编译指示或编译时标志。
请注意,上述内容最多只能使用32或64个元素(具体取决于体系结构)。如果你想要更多,你必须将模式分成多个值。
答案 1 :(得分:0)
扩展Chris Dodd的方法。
我认为您可以使用模式的符号列表生成您描述的内容。所以,从相同的X-macro设置开始。
#define PATTERNS(_) \
_(1, A B C D) \
_(2, A B) \
_(3, A D) \
/**/
#define A sum += values[0];
#define B sum += values[1];
#define C sum += values[2];
#define D sum += values[3];
#define GEN_FUNC(num, pattern) \
long sum_accoring_to_pattern ## num (int *values) { \
long sum = 0; \
pattern \
return sum; \
}
PATTERNS(GEN_FUNC)
贯穿cpp -P genpat.c | indent -gnu -i4 -br -ce -cdw -nbc -brf -brs -l100 -bbo
收益
long
sum_accoring_to_pattern1 (int *values) {
long sum = 0;
sum += values[0];
sum += values[1];
sum += values[2];
sum += values[3];
return sum;
}
long
sum_accoring_to_pattern2 (int *values) {
long sum = 0;
sum += values[0];
sum += values[1];
return sum;
}
long
sum_accoring_to_pattern3 (int *values) {
long sum = 0;
sum += values[0];
sum += values[3];
return sum;
}
您还可以生成较短的表单。
#define PATTERNS(_) \
_(1, A B C D) \
_(2, A B) \
_(3, A D) \
/**/
#define A + values[0]
#define B + values[1]
#define C + values[2]
#define D + values[3]
#define GEN_FUNC(num, pattern) \
long sum_accoring_to_pattern ## num (int *values) { \
return pattern ;\
}
PATTERNS(GEN_FUNC)
您几乎肯定希望#undef
A
.. D
后记。 :)