在C中,指向函数作为结构成员的指针是如何有用的?

gr8qqesn  于 11个月前  发布在  其他
关注(0)|答案(6)|浏览(119)

我对C编程并不陌生。但我不明白为什么在C中将指向函数的指针作为结构成员是有用的。示例:

// Fist Way: To keep pointer to function in struct
    struct newtype{
        int a;
        char c;
        int (*f)(struct newtype*);
    } var;
    int fun(struct newtype* v){
        return v->a;
    }
    
    // Second way: Simple
    struct newtype2{
        int a;
        char c;
    } var2;
    int fun2(struct newtype2* v){
        return v->a;
    }
            
    int main(){
    
        // Fist: Require two steps
        var.f=fun;
        var.f(&var);
        
        //Second : simple to call
        fun2(&var2);    
    }

字符串
程序员是用它来给予面向对象(OO)的形式给他们的C代码并提供抽象对象,还是只是让代码看起来像技术性的?
我认为在上面的代码中,第二种方法更温和,也很简单。在第一种方法中,我们仍然需要传递&var,即使fun()是结构体的成员。
如果在结构定义中保留函数指针是好的,请解释原因。

uurity8g

uurity8g1#

提供指向结构上的函数的指针可以使您动态选择要对结构执行的函数。

struct newtype{
    int a;
    int b;
    char c;
    int (*f)(struct newtype*);
} var;

int fun1(struct newtype* v){
        return v->a;
    }

int fun2(struct newtype* v){
        return v->b;
    }

void usevar(struct newtype* v) {
   // at this step, you have no idea of which function will be called
   var.f(&var);
}

int main(){
        if (/* some test to define what function you want)*/) 
          var.f=fun1;
        else
          var.f=fun2;
        usevar(var);
    }

字符串
这使您能够拥有单个调用接口,但根据测试是否有效而调用两个不同的函数。

thigvfpy

thigvfpy2#

如果你想做一些“基于对象”的编程,它很有用。
如果你曾经看过雷神之锤3引擎的源代码,你可以清楚地看到,大多数“实体”都有定义它们的属性,以及它们所做的工作[这是函数指针]。
分离属性和函数(通过C中的函数指针)定义了“结构”对象的属性和它们可以执行的操作。
举例来说:

struct _man{
   char name[];
   int age;
   void (*speak)(char *text);
   void (*eat)(Food *foodptr);
   void (*sleep)(int hours); 
   /*etc*/
};

void grijesh_speak(char *text)
{
   //speak;
}

void grijesh_eat(Food *food)
{
   //eat
}

void grijesh_sleep(int hours)
{
   //sleep
}

void init_struct(struct _man *man)
{
    if(man == NULL){ man = malloc(sizeof(struct _man));}
      strcpy(*man.name,"Grijesh");
      man->age = 25;
      man->speak = grijesh_speak;
      man->eat = grijesh_food;
      man->sleep = grijesh_sleep;
//etc
}

//so now in main.. i can tell you to either speak, or eat or sleep.

int main(int argc, char *argv[])
{
    struct _man grijesh;
    init_struct(&grijesh);
    grijesh.speak("Babble Dabble");
    grijesh.sleep(10);
    return 0;
}

字符串

jei2mxaa

jei2mxaa3#

我过去用它在C中实现了泛型容器。
举例来说:

typedef struct generic_list_node {
  void *data;
  struct generic_list_node *next;
} generic_list_node_t;

typedef struct generic_list {
  generic_list_node_t *head;
  void *(*copy)(void *data);                 
  void (*delete)(void *data);                
  int (*compare)(void *lhs, void *rhs);      
  void (*display)(void *data, FILE *stream);
} generic_list_t;

字符串
列表结构本身是数据不可知的,使用void *来表示数据项,并将所有类型感知的操作委托给上面的指针所指示的函数:

int insert(generic_list_t l, void *data)
{
  generic_list_node_t *cur = l.head;
  generic_list_node_t *new = malloc(sizeof *new);
  if (new)
  {
    new->data = l.copy(data);
    new->next = NULL;

    if (l.head == NULL)
    {
      l.head = new;
    }
    else
    {
      while (cur->next && l.compare(new->data, cur->data) > 0)
        cur = cur->next;
      new->next = cur->next;
      cur->next = new;
      printf("Successfully added ");
      l.display(data, stdout);
      printf(" to list\n");

    }
    return 1;
  }

  return 0;
}


1.对于“通用”和“容器”的适当宽松的定义,

wwtsj6pe

wwtsj6pe4#

这在嵌入式系统或驱动程序编写中特别有用。函数是使用函数指针调用的。
例如

struct_my_filesystem.open=my_open;
struct_my_filesystem.read=my_read;

字符串

zf2sa74q

zf2sa74q5#

在C语言中,有时候你需要调用一个函数,而不需要预先知道它的实现。例如,如果你正在开发一个在不同项目中使用的独立库。在这种情况下,向上下文结构添加一个函数指针并将其沿着传递给库函数是非常有意义的。然后库函数可以在运行时调用你的函数,而不必包含定义它的头文件。
它确实类似于你在做面向对象编程时所做的事情。在C中,你通常传递上下文变量,例如一个结构,将一组变量和可能对该上下文有意义的函数组合在一起。这接近于OO编程中的等价,在OO编程中,你示例化一个类并在示例上设置所需的变量。

30byixjq

30byixjq6#

这里有一个项目来帮助解释函数指针的用处。尝试创建一个基于c的库,提供继承和多态性。或者,尝试重新创建“C with Classes”。结构内的函数指针将是至关重要的。http://www.cs.rit.edu/~ats/books/ooc.pdf

相关问题