2012-10-19 33 views
7

我对C编程并不陌生。但我不明白什么是有用的,以保持指针在C中作为结构成员的功能。指针如何用作C中有用的struct成员?

// 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()也是struct的成员。

如果它在结构定义中保留函数指针很好,请帮忙解释一下原因。

+2

想想C++类中的虚函数。它们在引擎盖下以相似的方式实施。 –

+2

[关于嵌入式系统中的函数指针](http://stackoverflow.com/questions/4836245/function-pointers-in-embedded-systems-are-they-useful)。 – Lundin

+0

谢谢@Lundin!我在那找到真正非常有用和有趣的答案。 –

回答

11

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

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=fun; 
     else 
      var.f=fun2; 
     usevar(var); 
    } 

这让你保持只有一个代码的能力,但调用两个不同的功能,而你的测试是否有效。

+0

这是所有的想法......在C++中调用多态(运行时或编译绑定) –

1

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

例如

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

10

它的有用的,如果你正在试图做一些“基于对象”的节目。

如果您见过Quake 3引擎的源代码,您可以清楚地看到大多数“实体”具有定义它们的属性以及它们所做的工作[它们是函数指针]。

分离属性和函数(通过C中的函数指针)定义了一个“struct”对象的属性和它们可以执行的操作。

例如:

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; 
} 
1

有时在C你需要调用一个函数,而无需知道其实现的前期。例如。如果您正在开发用于不同项目的独立库。在这种情况下,将一个函数指针添加到上下文结构并将其传递给库函数是非常有意义的。然后,库函数可以在运行时调用您的函数,而不必包含定义它的头文件。

这的确与您在做面向对象编程时所做的类似。在C中,你通常会绕过上下文变量,例如一个结构,将一组变量和可能的功能组合在一起,这些变量对于该上下文是有意义的。这与OO编程中的eqvuivalent非常接近,您可以在其中实例化一个类并在实例上设置所需的变量。

2

我以前用这个来实现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.对于适当地松散定义的 “通用” 和 “容器”

+0

非常好用......谢谢 –

1

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

+0

这是很好的参考......谢谢! –