Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C: Putting a function pointer in a structure where the function uses that structure as an argument

I seem to have run into a chicken and egg problem.

I want to have a structure that as one of its members is a function pointer. However this function pointer wants to use that same structure as it's argument. This creates an issue where I have to define the function pointer before I can include it as a member, but I can't properly define it until I've defined the structure.

I have found that if I simply leave the argument list for the function pointer blank it SEEMS to work, though what I have read is that this is potentially fraught with issues.

Below is what I currently have:

#include <stdio.h>

typedef void (*IO_fun_ptr_t)();

typedef struct IO_config_t{
  int                   address;
  IO_fun_ptr_t          IO_fun_ptr; //pointer to the function to be used
} IO_config_t;

void print_address (IO_config_t *input){
  printf("The address is %d \n", input->address);
  printf("Push any key to continue:");
  getchar();
}

void main()
{
  IO_config_t             input = {.address = 16,
                                   .IO_fun_ptr = &print_address};

  input.IO_fun_ptr(&input);

}

The result is:

The address is 16 
Push any key to continue:

This works but I'm concerned about the potential implications of leaving that argument blank.

As a bit of an aside, I originally thought that I should be able to use void* as an argument as a placeholder for pointer to an unknown argument type, but I would get compile errors when doing so at the point where I assign the pointer to my function:

typedef void (*IO_fun_ptr_t)(void *);

(Error[Pe144]: a value of type "void (*)(IO_config_t *)" cannot be used to initialize an entity of type "IO_fun_ptr_t")

Any advice on how to do this better and cleaner?

like image 223
MidnightRover Avatar asked Feb 26 '18 16:02

MidnightRover


2 Answers

Use forward-declarations.

This is a way of stating that a structure exists, but without providing details of all the members of the structure until later.

#include <stdio.h>

// 1.) Forward declaration: Here is the name of the structure
// but member-details are omitted.
struct IO_config_t;

// 2.) typedef of the structure
// Still no details on the members.
typedef struct IO_config_t  IO_config_t;

// 3.) The parameter to the function is listed, using the definition
// from step 2.)  (note: Still no details on the members yet)
typedef void (*IO_fun_ptr_t)(IO_config_t* input);

// 4.) Now we actually detail the members of the structure
struct IO_config_t{
  int                   address;
  IO_fun_ptr_t          IO_fun_ptr;
};

void print_address (IO_config_t *input){
  printf("The address is %d \n", input->address);
  printf("Push any key to continue:");
  getchar();
}

void main()
{
  IO_config_t input = {.address    = 16,
                       .IO_fun_ptr = &print_address};

  input.IO_fun_ptr(&input);

}

This is demonstrated in the short program: https://ideone.com/p3jBYt

like image 170
abelenky Avatar answered Sep 30 '22 02:09

abelenky


So I had searched through stack exchange and couldn't find anything so humbled myself to asking a question. Just as I'm getting to the end of writing everything up, I glance over to the "Similar Questions" box to the right, and I happen to see the following question that I didn't come across before:

How to properly define a function pointer in struct, which takes struct as a pointer?

And in its answer I found my answer. I simply have to define the function pointer in the structure itself, not before hand. (I had tried, but forgot to include the struct keyword in the definition so it didn't work since the type def wasn't complete I am guessing).

Below is what compiles clean and seems to work:

#include <stdio.h>

typedef struct IO_config_t{
  int                   address;
  void                  (*IO_fun_ptr)(struct IO_config_t *); //pointer to the function to be used
} IO_config_t;


void print_address (IO_config_t *input){
  printf("The address is %d \n", input->address);
  printf("Push any key to continue:");
  getchar();
}

void main()
{
  IO_config_t             input = {.address = 16,
                                   .IO_fun_ptr = &print_address};

  input.IO_fun_ptr(&input);
}
like image 28
MidnightRover Avatar answered Sep 30 '22 00:09

MidnightRover