使用像宏这样的位图在编译时创建一个函数
Creating a function in compile time using a bitmap like macro
我有一个 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 结构来实现吗?因为我试图保留所有内容,所以我不想编写脚本来为我生成代码。我需要的是使用位图宏之类的东西指定模式,而不是在编译时生成函数。
我的方法是使用一个定义了所有你想要的模式的宏,结合其他定义函数或你需要的关于它们的信息的宏。所以你会有这样的东西:
#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
现在您可以轻松声明所有函数并构建 table 个指向它们的指针:
FUNCTION_PATTERNS(DEFINE_SUM_FUNCTION)
long (*sum_functions[])(int *) = { FUNCTION_PATTERNS(SUM_FUNCTION_NAME) };
如果需要,您可以在 DEFINE_SUM_FUNCTION
宏中手动展开循环,或者您可以依靠您的 C 编译器为您完成,可能需要适当的 pragma 或编译时标志。
请注意,以上内容最多只能处理 32 或 64 个元素(取决于架构)。如果您想要更多,则必须将模式拆分为多个值。
扩展 Chris Dodd 的方法。
我认为您可以通过使用模式符号列表来准确生成您所描述的内容。因此,从相同的 X 宏设置开始。
#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
后记。 :)
我有一个 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 结构来实现吗?因为我试图保留所有内容,所以我不想编写脚本来为我生成代码。我需要的是使用位图宏之类的东西指定模式,而不是在编译时生成函数。
我的方法是使用一个定义了所有你想要的模式的宏,结合其他定义函数或你需要的关于它们的信息的宏。所以你会有这样的东西:
#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
现在您可以轻松声明所有函数并构建 table 个指向它们的指针:
FUNCTION_PATTERNS(DEFINE_SUM_FUNCTION)
long (*sum_functions[])(int *) = { FUNCTION_PATTERNS(SUM_FUNCTION_NAME) };
如果需要,您可以在 DEFINE_SUM_FUNCTION
宏中手动展开循环,或者您可以依靠您的 C 编译器为您完成,可能需要适当的 pragma 或编译时标志。
请注意,以上内容最多只能处理 32 或 64 个元素(取决于架构)。如果您想要更多,则必须将模式拆分为多个值。
扩展 Chris Dodd 的方法。
我认为您可以通过使用模式符号列表来准确生成您所描述的内容。因此,从相同的 X 宏设置开始。
#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
后记。 :)