Grijesh Chauhan
Grijesh Chauhan

Reputation: 58271

How are pointers to functions as struct members useful in C?

I am not new to C programming. But I don't understand why keeping a pointer to a function as a structure member is useful in C. Example:

    // 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);    
    }

Do programmers use it to give an Object-Oriented (OO) shape to their C code and provide abstract objects, or just to make code look technical?

I think that in the above code the second way is more gentle and pretty simple too. In the first way, we still have to pass &var, even though fun() is member of the struct.

If it's good to keep function pointers within a struct definition, kindly explain the reason.

Upvotes: 8

Views: 13214

Answers (6)

tomahh
tomahh

Reputation: 13651

Providing a pointer to function on a structure can enable you to dynamically choose which function to perform on a structure.

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

This gives you the ability to have a single calling interface, but calling two different functions depending on if your test is valid or not.

Upvotes: 11

Jonathan Henson
Jonathan Henson

Reputation: 8206

Here is a project to help explain the usefulness of function pointers. Try to create a c-based library providing inheritance and polymorphism. Or, try and recreate "C with Classes". Function pointers inside structures will be vital. http://www.cs.rit.edu/~ats/books/ooc.pdf

Upvotes: 1

John Bode
John Bode

Reputation: 123448

I've used this in the past to implement generic containers1 in C.

For example:

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;

The list structure itself is data-agnostic, using void * to represent data items, and delegates all type-aware operations to the functions indicated by the pointers above:

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. For suitably loose definitions of "generic" and "container"

Upvotes: 2

Stragulus
Stragulus

Reputation: 1113

Sometimes in C you need to call a function, without knowing its implementation upfront. E.g. if you're developing a stand-alone library used in different projects. In that case, it makes perfect sense to add a function pointer to a context struct and pass that along to the library functions. The library functions can then call your function at run-time without having to include the header files that define it.

It is indeed similar to what you do when doing Object Oriented programming. In C, you usually pass around context variables, e.g. a struct, grouping together a set of variables and possibly functions that are meaningful for that context. This is close to the eqvuivalent in OO programming, where you instantiate a class and set the required variables on the instance.

Upvotes: 1

Aniket Inge
Aniket Inge

Reputation: 25695

Its useful if you're trying to do some sort of "object based" programming.

If you've ever seen the Quake 3 engine's source code.. you can see clearly that most "entities" have attributes that define them, and the work they do[which are the function pointers].

Segregating attributes and functions(through function pointers in C) defines a "struct" object's attributes and actions they can do.

For example:

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

Upvotes: 11

anishsane
anishsane

Reputation: 20980

This can be particuarly useful in embedded system, or driver writing. The functions are called using function pointers.

e.g.

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

etc

Upvotes: 1

Related Questions