coolcracker
coolcracker

Reputation: 61

How do I declare a function to be used as a function pointer in c?

I am confused with function pointer declaration.

I have an api abc() which takes an argument as so:

void abc(void (*my_func)(void *p), int, int)

If I want to pass my function as an argument to that api, I am declaring it in my .h file:

void (*xyz)(void *p)

and defining as:

void *(xyz)(void *p){
statements;
}

but this throws an error. Please correct me.

Upvotes: 2

Views: 281

Answers (6)

Shahbaz
Shahbaz

Reputation: 47493

If I understood correctly, you want xyz to be the function that is passed to abc, right?

As the argument my_func indicates, you have a pointer to a function that takes void * as argument and returns void

 type (*func_pointer)(type, type, type, .......)
   ^   ^       ^        ^     ^     ^
   |   |       |        |     |     |
   |   |       |        argument types
   |   |   pointer name
   | This is a function pointer
return type

Therefore, you need to declare xyz as:

void xyz(void *p);

And the same in implementation:

void xyz(void *p){
    statements;
}

What you are doing wrong is that, the line you wrote in the .h file defines a function pointer, named xyz. The function pointer has no value, because you never wrote xyz = some_function;

What you have written in the source file is a function, also with name xyz that takes a void * as input and returns a void *, instead of void which was your intention.

Maybe this helps you get less confused:

When you write int *x;, x is a pointer to int. Then you can have int y; that doesn't have an extra * and write x = &y;.

It's the same with functions. If you have void (*funcptr)(void *p);, then all you need is a function that says void some_func(void *p){} (again without the extra *) and write funcptr = some_func;. You don't need the & since function names are in fact pointer to the function. You could put it to be more explicit though.

Upvotes: 1

glglgl
glglgl

Reputation: 91017

The (*xyz) means that it is a function pointer.

Function pointers are best handled with typedefs. So it is guaranteed that there is nothing wrong.

I would do the following:

// define a type for the function (not its pointers, as you can often read)
typedef void my_func_t(void *p);

void abc(my_func_t*, int, int);

// declaration in order to be type-safe - impossible if only the pointer would be typedef'd
my_func_t my_func_impl; 

// definition:
void my_func_impl(void *p)
{
    do_something_with(p);
}

and then you can call your abc() with abc(my_func_impl, 47, 11). You can put a & before my_func_impl there in order to point out that it is the function address you wish to obtain, but it is optional.

An alternative would be to write

typedef void (*my_func_p)(void *p);

and use my_func_p instead of my_func_t *, but this has the disadvantage that you cannot write my_func_t my_func_impl;.

Why would you want to do that?

Well, if, by any coincidence or accident, the function definition or the typedef is changed, they won't match any longer, but the collision is not declared as error, but only as warning (Mismatch pointer). OTOH, my_func_t my_func_impl; serves as a kind of prototype, which causes a function header mismatch, which is an error.

Upvotes: 3

azat
azat

Reputation: 3565

This works

void abc(void* (*my_func)(void*), int a, int b) {
    my_func(0);
}

void *(xyz)(void *p) {}

int main() {
    abc(xyz, 0, 0);
    return 0;
}

When you write void (*my_func)(void *p) it means pointer to function, that returns void And void (*my_func)(void *p) it means pointer to function, that returns pointer

Upvotes: 0

Mike Seymour
Mike Seymour

Reputation: 254431

Simply declare and define your function as you would any other:

void xyz(void *p);

void xyz(void *p){
    // ...
}

and pass a pointer to the API:

abc(xyz, 42, 7);

Function names are automatically interpreted as function pointers where appropriate. You can also explicitly take the address of the function, if brevity isn't your thing:

abc(&xyz, 42, 7);

Upvotes: 1

Arnaldo Yokomizo
Arnaldo Yokomizo

Reputation: 1

The first argument of 'abc' is the pointer of function returning 'void' and having 'void *' as an argument...

So your code should look like:

void
myFunc (void *) 
{
   // ... my statements
}

...

abc (myFunc, 10, 20);

Upvotes: 0

Nate
Nate

Reputation: 12819

you just need to declare it:

void xyz(void *p);

with the implementation the same way.

When you pass it into your api, the type system figures out it out automatically:

abc(xyz,someint,anotherint);

Upvotes: 4

Related Questions