概括函数指针

时间:2015-11-18 18:33:40

标签: c pointers function-pointers

昨天晚上我写了下面的代码来执行一些算术运算(求和,乘法,减法,除法)。

 data operation(int oper, data e1, data e2){
   data res;
   basic b;
   //pointer to a funcion that takes two int input and return an int
   int (*funIntPtr)(int,int);
   float (*funFloatPtr)(float,float);

   funIntPtr = NULL;
   funFloatPtr= NULL;
   //I look for the function to be called
     switch (oper) {
       case MINUS:
         //*functionPtr = &subInt;
         switch (e1.b.type) {
           case basic_int_value:funIntPtr = subInt;break;
           case basic_float_value:funFloatPtr = subFloat;break;
           case basic_boolean_value:
             yyerror("boolean arithmetic operation are NOT_ALLOWED");
             exit(NOT_ALLOWED);
             break;
         }
         break;
       case PLUS :
         switch (e1.b.type) {
           case basic_int_value:funIntPtr = addInt;break;
           case basic_float_value:funFloatPtr = addFloat;break;
           case basic_boolean_value:
             yyerror("boolean arithmetic operation are NOT_ALLOWED");
             exit(NOT_ALLOWED);
             break;
         }
         break;
       case MULTIPLY:
         switch (e1.b.type) {
           case basic_int_value:funIntPtr = mulInt;break;
           case basic_float_value:funFloatPtr = mulFloat;break;
           case basic_boolean_value:
             yyerror("boolean arithmetic operation are NOT_ALLOWED");
             exit(NOT_ALLOWED);
             break;
         }
         break;
       case DIVIDE :
         switch (e1.b.type) {
           case basic_int_value:funIntPtr = divInt;break;
           case basic_float_value:funFloatPtr = divFloat;break;
           case basic_boolean_value:
             yyerror("boolean arithmetic operation are NOT_ALLOWED");
             exit(NOT_ALLOWED);
             break;
         }
         break;
       default:
         yyerror("what now?");
         exit(BUGGY_THE_CLOWN);
         break;
      }
    //look for values to be used
    if( funIntPtr == NULL && funFloatPtr == NULL){
      yyerror("no function found for the specified operation..");
      exit(BUGGY_THE_CLOWN);
    }
    res.type = basic_dataType;
    res.b.type = e1.b.type;//inherithed
    switch (e1.b.type) {
      case basic_int_value:
        {
          res.b.i = funIntPtr(e1.b.i, e2.b.i);
        }
        break;
      case basic_float_value:
        {
          res.b.f = funFloatPtr(e1.b.f, e2.b.f);
        }
        break;
      case basic_boolean_value:
      default:
        yyerror("no data found for the specified operation..");
        exit(BUGGY_THE_CLOWN);
    }
   return res;
 }

在第一部分中,我找到了要使用的函数,在第二部分中,我收集了要使用的输入数据。它工作正常,它有助于达到目的。

typedef struct data{
    dataType type;
    union{
      complex c;
      basic b;
    };
}data;

data是一个包含基本类型值或复杂值的结构。复杂值是数组类型和结构。关于哪一方,我暂时不在乎。

typedef struct basic{
  basicType type;
  union{
     int i;
     float f;
     bool b;
  };
}basic;

基本值atm只包含整数,浮点数和布尔值。

但我想知道我是否可以让它更紧凑和高效。 例如,我已声明了两个函数指针,但我只使用其中一个。有没有办法概括函数指针?

我知道我必须声明输入类型和返回类型,但在这种情况下,推迟这样的函数特化以便只有一个指针会很棒。 是否有可能或应该改变我解决问题的方式?

任何建设性的建议都被广泛接受:)

2 个答案:

答案 0 :(得分:0)

在您的示例中,我没有看到使用的浮点函数:

  case basic_float_value:
    {
      res.b.i = funIntPtr(e1.b.i, e2.b.i);
    }

我希望有类似的东西:

  case basic_float_value:
    {
      res.b.f = funFloatPtr(e1.b.f, e2.b.f);
    }

这就是你不能使用单个函数指针的原因:float(double)和integer参数传递给函数的方式和返回结果的方式有很大的不同。当然你可以做重型转换,只是为了保存一个函数指针,但这会混淆代码所以我建议反对。

答案 1 :(得分:0)

您可以使用以下结构:

/* Operations enum */
enum operation {
    ADD, SUB, DIV, MUL, OP_COUNT
};

/* Operation arity */
static const int arity[OP_COUNT] = {
    [ADD] = 2, [SUB] = 2, [DIV] = 2, [MUL] = 2
};

/* Operation function pointer */
typedef double (*Operator)(double* arguments);

/* Map operation to operator */
Operator operators[OP_COUNT] = {
    [ADD] = add, [SUB] = sub, [DIV] = div, [MUL] = mul
};

double add(double *arguments) { return arguments[0] + arguments[1]; }
/* and so on for other operators */

此外,您可能希望合并arityoperators地图。

还有一件事是声明参数的静态数组可能需要知道arity值中的最大值。这种结构可以让你实现任意运算符而无需重写代码。

此外,您可以使用任何您想要的通用值结构,而不是double