我想在C99中将运算符作为参数传递。 我的解决方案是:
int add(int l, int r)
{
return l + r;
}
int sub(int l, int r)
{
return l - r;
}
// ... long list of operator functions
int perform(int (*f)(int, int), int left, int right)
{
return f(left, right);
}
int main(void)
{
int a = perform(&add, 3, 2);
}
还有其他方法吗?我不想为每个操作员编写一个函数。
看起来像这样:
int a = perform(
的 something_cool_here , 3, 2);
答案 0 :(得分:4)
您可以使用开关/案例,例如:
int perform(char op,int a,int b)
{
switch (op)
{
case '+': return a+b;
case '-': return a-b;
default: return 0;
}
}
但是你仍然需要为每个运算符编写一些代码;你不能在C中免费获得任何东西。
答案 1 :(得分:3)
您可以使用X Macros。通过在可重定义宏中定义包含重复值表的单个宏,您可以重新定义当前任务的内部宏,并插入一个宏来处理整个集。
这是一个以单操作数浮点内置为例的紧凑方法。其他类型的过程类似。
//add name of each function you want to use here:
#define UNARYFPBUILTINS \
$(acos) $(acosh) $(asin) $(asinh) $(atan) $(atanh) $(cbrt) $(ceil) \
$(cos) $(erf) $(erfc) $(exp) $(exp10) $(exp2) $(expm1) $(fabs) \
$(floor) $(gamma) $(j0) $(j1) $(lgamma) $(log) $(log10) $(log1p) \
$(log2) $(logb) $(pow10) $(round) $(signbit) $(significand) \
$(sin) $(sqrt) $(tan) $(tgamma) $(trunc) $(y0) $(y1)
//now define the $(x) macro for our current use case - defining enums
#define $(x) UFPOP_##x,
enum ufp_enum{ UNARYFPBUILTINS };
#undef $ //undefine the $(x) macro so we can reuse it
//feel free to remove the __builtin_## ... its just an optimization
double op(enum ufp_enum op, double f){
switch(op){ //now we can use the same macros for our cases
#define $(x) case UFPOP_##x : f = __builtin_##x(f);break;
UNARYFPBUILTINS
#undef $
}
return f;
}
您可以继续将其用于其他内容
///////////EXTRA STUFF/////////
//unused - may be good mapping the enums to strings
//#define $(x) #x,
//const char * ufp_strings{ UNARYFPBUILTINS };
//#undef $
//this uses float instead of double, so adds the ##f to each function
float opf(enum ufp_enum op, float f){
switch(op){
#define $(x) case UFPOP_##x : f = __builtin_##x##f(f);break;
UNARYFPBUILTINS
#undef $
}
return f;
}
//you could do the same thing for long double here
编辑:请注意,宏中的$是依赖于实现的,你可以调用它
Edit2:这是一个有多个参数来做算术运算符的例子。这个使用计算得到的而不是开关,以防你的编译器比另一个更好地处理一个。
#define IOPS $(SUB,-) $(MUL,*) $(DIV,/) $(MOD,%) $(ADD,+) $(AND,&) $(OR,|) \
$(XOR,^) $(SR,>>) $(SL,<<)
enum iops_enum {
#define $(x,op) IOPSENUM_##x,
IOPS
IOPSENUM_COUNT
#undef $
};
int opi(int a, enum iops_enum b, int c){
static const char array[] = { //you may get better results with short or int
#define $(x,op) &&x - &&ADD,
IOPS
#undef $
};
if (b >= IOPSENUM_COUNT) return a;
goto *(&&ADD + array[b]);
//else should give a warning here.
#define $(x,op) x: return a op c;
IOPS
#undef $
}