You need to cast void* pointer to the function pointer first:
#include <stdio.h>
typedef struct {
void* fn;
void* param;
} event;
void print()
{
printf("Hello\n");
}
int main()
{
event e;
e.fn = print;
((void(*)())e.fn)();
return 0;
}
Of course, if this is really what you want. If you want your struct to contain pointer to the function, instead of void* pointer, use the proper type at the declaration:
typedef struct {
void (*fn)();
void* param;
} event;
Here you have fn declared as a pointer to the void function, and the param as void* pointer.
Videos
As far as i understood void(*)() works in a similiar way void* works, but with function pointers, meaning you can cast any function pointer to it and back. Is this correct? However, i ran into a strange issue.
void foo(int i) {
}
void bar(char c) {
}
void test(void(*)()) {
}
int main() {
test(foo); //test(bar); compile error
}
I get an incompatible pointer type error if i try to pass a function with param char, but it works with param int, why would that be? Thanks!
I apologize for the formatting, writing from my phone.
You need to cast void* pointer to the function pointer first:
#include <stdio.h>
typedef struct {
void* fn;
void* param;
} event;
void print()
{
printf("Hello\n");
}
int main()
{
event e;
e.fn = print;
((void(*)())e.fn)();
return 0;
}
Of course, if this is really what you want. If you want your struct to contain pointer to the function, instead of void* pointer, use the proper type at the declaration:
typedef struct {
void (*fn)();
void* param;
} event;
Here you have fn declared as a pointer to the void function, and the param as void* pointer.
event is a type, not an object or expression. You can't access a member of a structure type, only of an object of a structure type.
So given:
typedef struct {
void* fn;
void* param;
} event;
you need to have an object of type event, and you need to assign values to its members.
In your question, you use fn as a member name, but then you refer to something called function. I'll assume here that they're supposed to be the same thing, and that fn is supposed to point to some function.
You can't portably store a function pointer in a void*. On many, probably most, implementations you can get away with it, but it's not guaranteed by the language. (There are systems were function pointers are bigger than data pointers, and converting a function pointer to void* loses information.) On the other hand, all pointer-to-function types are convertible to each other, and a round-trip conversion is guaranteed to give you the original pointer value.
I'll assume (I'm making a lot of assumptions here because you didn't provide a lot of information) that you want fn to point to a function that takes a void* argument and doesn't return a result; then making param a void* makes sense. For consistency with that assumption, we can alter your type definition:
typedef struct {
void (*fn)(void*);
void *param;
} event;
(The void (*fn)(void*); syntax is not entirely obvious. I used cdecl to construct it.)
Now you can define an object of type event:
event e = { some_func, NULL };
You have to have defined some_func somewhere, as
void some_func(void *param { /* ... */ }
or equivalent. Now you can call that function indirectly through the event object e:
e.fn(e.param);
Or, if it's more convenient to have a pointer to an event:
event *ptr = malloc(sizeof *ptr);
if (event == NULL) {
/* error handling here */
}
ptr->fn = some_func;
ptr->param = NULL;
and you can use indirection both on the pointer-to-event and on the function pointer contained in the event object it points to:
ptr->fn(ptr->param);
Depending on what you're trying to accomplish, you might want fn to be able to point to functions of different types. If you do that, you must convert (with an explicit cast) e.fn or ptr->fn to the actual type of the function it points to before making a call through it. You can't blindly mix function pointers of different types; if you do, the result is either a compile-time error or run-time undefined behavior. You can use void (*)(void) (pointer to function with no parameters and returning no result) as a "generic" function pointer type, but unlike with void* any conversions to the type you need must be explicit.)
I want to know how to make the function call both with and without using the additional
void*param.
To call a function with no argument, simply use () in the function call. But again, for a given function, you can't choose to call it with or without a parameter; the call has to match the definition. (Except perhaps for variadic functions like printf, but you still need a function pointer of the correct type, and a variadic function can't be called with no arguments.)
A pointer to void is a "generic" pointer type. A void * can be converted to any other pointer type without an explicit cast. You cannot dereference a void * or do pointer arithmetic with it; you must convert it to a pointer to a complete data type first.
void * is often used in places where you need to be able to work with different pointer types in the same code. One commonly cited example is the library function qsort:
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
base is the address of an array, nmemb is the number of elements in the array, size is the size of each element, and compar is a pointer to a function that compares two elements of the array. It gets called like so:
int iArr[10];
double dArr[30];
long lArr[50];
...
qsort(iArr, sizeof iArr/sizeof iArr[0], sizeof iArr[0], compareInt);
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareDouble);
qsort(lArr, sizeof lArr/sizeof lArr[0], sizeof lArr[0], compareLong);
The array expressions iArr, dArr, and lArr are implicitly converted from array types to pointer types in the function call, and each is implicitly converted from "pointer to int/double/long" to "pointer to void".
The comparison functions would look something like:
int compareInt(const void *lhs, const void *rhs)
{
const int *x = lhs; // convert void * to int * by assignment
const int *y = rhs;
if (*x > *y) return 1;
if (*x == *y) return 0;
return -1;
}
By accepting void *, qsort can work with arrays of any type.
The disadvantage of using void * is that you throw type safety out the window and into oncoming traffic. There's nothing to protect you from using the wrong comparison routine:
qsort(dArr, sizeof dArr/sizeof dArr[0], sizeof dArr[0], compareInt);
compareInt is expecting its arguments to be pointing to ints, but is actually working with doubles. There's no way to catch this problem at compile time; you'll just wind up with a missorted array.
Using a void * means that the function can take a pointer that doesn't need to be a specific type. For example, in socket functions, you have
send(void * pData, int nLength)
this means you can call it in many ways, for example
char * data = "blah";
send(data, strlen(data));
POINT p;
p.x = 1;
p.y = 2;
send(&p, sizeof(POINT));
You can write a perfectly fine generic function this way, but:
result = array[rand()%(length-1)];
This is dereferencing the void pointer array while also attempting to store it into a pointer result. What you want to store is the address at that offset:
result = array + rand()%(length-1);
However, you can't perform arithmetic like this on void pointers either, as the size of the underlying type is not known (some compilers allow sizeof(void)==1 as an extension). With a non-void array, the number of bytes a given element consumes, and thus the number of bytes to increment by when doing arithmetic on the address, is encoded in the type. In a generic function operating on void pointers like this one you'll need to explicitly pass the size of the type.
void *randomNum(void * array, size_t size, size_t length)
Now perform the calculation by casting array to a char pointer, which forces arithmetic on array to occur in increments of 1 byte times the provided size parameter:
result = (char*)array + (rand()%(length-1)) * size;
^ ^
You can then call randomNum with randomNum(array, sizeof(*array), 9)
However, you still need to cast the return value of the function before dereferencing it.
printf("%d\n", *(int*)randomNum(array,sizeof(*array),9));
There are a number of problems with the approach:
1) Since the argument array is of type void *, your plan of indexing it based on length will not work—for indexing to work, the length of each element in your array needs to be known as well. You seem to be trying to make a generic function that would work for any type of array, but honestly it's simpler to make a separate function for different types of arrays.
(To see why this is problematic, remember that array[index] is equivalent to *(array + index); by indexing the void * you are applying pointer arithmetic to and then dereferencing the void pointer. Meditate on this.)
2) You are dereferencing a void pointer when you do *randomNum(array, 9). This cannot be done; you need to cast the pointer to an appropriate type first, i.e., *((int *)randomNum(array, 9)), but as I said above, the whole approach with randomNum dealing in void pointers is problematic, so just change the whole thing to:
int *randomNumInt(int *array, size_t length)
So I want to be able to store 2 types of functions in an array: one that returns an int and one that doesn't return anything.
int add(int x, int y) {
return x + y;
}
void foo() {
printf("foo\n");
}
static void* funcs[] = {add, foo};My question is, how do I then cast the first pointer to a function pointer so I can call it? Same for the second.
The declaration is read as follows:
function -- function is a
*function -- pointer to
(*function) () -- function taking unspecified parameters
*(*function) () -- returning pointer to
void *(*function) (); -- void
So, function is a pointer to a function type, not a function itself. You could have multiple functions, each returning pointers to void:
void *foo( void ) { ... }
void *bar( void ) { ... }
void *bletch( void ) { ... }
You can use the function pointer to point to each of those functions, and decide at runtime which to call:
if ( condition1 )
function = foo;
else if ( condition2 )
function = bar;
else
function = bletch;
void *ptr = function(); // or (*function)();
The notation
void * (*function)();
means “declare a function pointer named function, which points to a function that takes an unspecified number of arguments, then returns a void *.”
Since this just declares a variable, it doesn’t define a function and so nothing can be said about what value is going to be returned. You’d need to assign this pointer to point to a function before you can call it.
Once you do assign function to point to something, if you call function, you’ll get back a void *, which you can think of as “a pure memory address” since it contains an address but can’t be dereferenced to an object without a cast.
Notice that returning a void * is not the same as as a function that has a void return type. The former means “I return a memory address,” and the latter means “I don’t return anything at all.”