1

I declared a struct like this one :

typedef struct s_data {

    char buff[2048];
    int len; 
    void *func[10];
    struct data *next;

}               t_data;

In my code, when passing a *data, I assigned some functions (just giving one so it is more understandable)

void init_data(t_data *data)
{
    data->len = 0;
    data->func[0] = &myfirstfunctions;
    //doing the same for 9 others

}

My first function would be something taking as argument *data, and an int. Then, I try to use this function in another function, doing

data->func[0](data, var);

I tried this and a couple of other syntaxes involving trying to adress (*func[0]) but none of them work. I kind of understood from other much more complex questions over there that I shouldn't store my function like this, or should cast it in another typedef, but I did not really understand everything as I am kind of new in programming.

2
  • void * is an untyped pointer. The compiler have no idea what the pointer is really pointing at, which means you can't dereference it without a cast to the correct type. The better solution is to make func an array of the correct type to begin with. A type-alias (created with typedef) for the function type helps. Commented Dec 17, 2020 at 13:15
  • Thanks @Someprogrammerdude ! Following your answer, I just tried to change my func array an array of int, as all my function will return an int. But when I try to assign it : data->func[0] = &myfirstfunction;, I got a warning of bad assignement ( 'int ' from 'int ()(t_data *, int)'). I think I understand from the warning that the problem comes from my arguments, but what am I missing ? Thx for your time, Commented Dec 17, 2020 at 13:31

3 Answers 3

2

void* can only be used reliably as a generic object pointer ("pointer to variables"). Not as a generic function pointer.

You can however convert between different function pointer types safely, as long as you only call the actual function with the correct type. So it is possible to do just use any function pointer type as the generic one, like this:

void (*func[10])(void);
...
func[0] =  ((void)(*)(void))&myfirstfunction;
...
((whatever)func[0]) (arguments); // call the function

As you might note, the function pointer syntax in C is horrible. So I'd recommend using typedefs:

typedef void genfunc_t (void);
typedef int  somefunc_t (whatever*); // assuming this is the type of myfirstfunction

Then the code turns far easier to read and write:

genfunc_t* func [10];
...
func[0] = (genfunc_t*)&myfirstfunction;
...
((somefunc_t*)func[0]) (arguments);
Sign up to request clarification or add additional context in comments.

Comments

0

If all of your functions will have the same signature, you can do this like:

#include <stdio.h>

typedef void (*func)(void *, int);

struct s_data {
        char buff[2048];
        int len;
        func f[10];
        struct s_data *next;
};

static void
my_first_function(void *d, int x)
{
        (void)d;
        printf("%d\n", x + 2);
}

static void
init_data(struct s_data *data)
{
        data->len = 1;
        data->f[0] = my_first_function;
}

int
main(void)
{
        struct s_data d;
        init_data(&d);
        d.f[0](NULL, 5);
        return 0;
}

If your functions have different signatures, you will want to either use a union, or perhaps you will need several different members of the struct to store the function pointers.

2 Comments

why do you need to do (void)d , sir?
@snr The (void) cast is to suppress the compiler warning about the unused parameter.
0

The problem is that you haven't actually declared an array of function pointers. What you actually did is an array of pointers to void.

The syntax of declaring a pointer to function is as following:

function_return_type (*pointer_name)(arg1_type,arg2_type,...);

Then you can create an array of pointers to functions:

function_return_type (*arr_name[])(arg1_type, arg2_type,...)

Therefore, the declaration of your structure should look like this:

typedef void (*pointer_to_function)(void *, int);

struct s_data {
        char buff[2048];
        int len;
        pointer_to_function array_of_pointeters[10];
        struct s_data *next;
};

Good luck:)

2 Comments

Thank you, it worked ! To those interested, like above, I declared typedef void (*func)(void *, int); Then, func f[10]; in my struct. During assignement, I just had to cast my function into a (func) so data->f[0] = (func) &myfirstfunction; and it worked. Thanks again !
we have just passed this topic in our classroom, so your example was very helpful for us too

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.