function pointers query - c

what is the difference between these two below:
typedef void (*my_destructor)(void *);
typedef void (*my_destructor)(void *) my_func_ptr;
is the second one valid?

The first one declares a type called my_destructor. This type is a pointer to a function taking a parameter of type void* and returning nothing.
The second one is not valid, what are you trying to do ? If you want to declare a variable of type my_destructor, you have to do this:
typedef void (*my_destructor)(void *);
my_destructor my_func_ptr;

You are declaring a type for a pointer function.
The first one is the good one it mean you have a type named my_destructor who is a pointer to a function (*my_destructor) that take a void pointer (void *) on arguments and who return nothing (void).
Now you can use your type as if it was another type like for example char, long or whatever.

Related

Generic function typedef in C - how to get rid of initialization warning?

I'm experimenting with generic-like code and I have a function like this (a lot of not relevant code removed):
typedef uint8_t (*struct_converter_t)(void *, char *);
void convert_struct(
struct_converter_t converter, // this is a function
const char * file_name
){
some_struct_t * some_struct;
converter(some_struct, some_string_buffer);
}
And when I try to assign a function that takes some_struct_t (not void *):
static uint8_t some_converter(some_struct_t * vd, char * s);
to my struct_converter_t like this:
struct_converter_t converter = some_converter; // WARNING HERE
I'm getting this:
initialization of 'struct_converter_t' {aka 'unsigned char (*)(void *, char *)'} from incompatible pointer type 'uint8_t (*)(some_struct_t *, char *)' {aka 'unsigned char (*)(struct <anonymous> *, char *)'} [-Wincompatible-pointer-types]
I'm not experienced in C and I would like to know if there is a way to get rid of this warning elegantly.
The function that you're assigning to the function pointer type has parameters that are incompatible with the function pointer.
Your function takes a some_struct_t * as the first parameter but the function pointer type takes a void * as the first parameter. While any object pointer can be converted to/from a void *, that does not extend to function pointer parameters.
You need to change your function to take a void * for its first parameter to be compatible with the function pointer. Then inside the function you can convert that void * parameter to a some_struct_t *.
In C, you can supply an argument of type X* to a function expecting a void*. But that's as far as the conversion goes. You cannot take a function whose first parameter is an X* and use it as the argument for a parameter which is a function whose first parameter is a void*.
The reason is that C does not guarantee that X* and void* have the same representation. It does guarantee that the compiler knows how to convert an X* into a void* in a way that does not destroy information, so that it can be later converted back to an X*. But the void* might look quite different.
So the compiler can insert code which changes the X* to a void*. But how does it change a char*(*)(X*) (a function whose parameter is an X*) to a char*(*)(void*)? If the function is expecting that arg has type char*(*)(void*), then it will mostly likely call arg(v) where v has type void*. What then happens if arg actually expects an X*?
In order for the compiler to allow that possibility, it would have to somehow wrap arg in what's usually called a trampoline; a function which accepts an X* and converts it into a void* in order to call a different function. That's not so easy -- for one thing, it would have to store the trampoline somewhere -- so C refuses to do it as an automatic conversion.

What does this expression: void* (*fct)(void*(*)(void*), void*)?

I know that e.g.
void *(*myFuncName)(void*)
is a function pointer that takes and also returns void*.
Is this a pointer which takes 2 arguments?
A void pointer another function of that type returning void* and a void*?
I'm just guessing..
void* (*fct)(void*(*)(void*), void*);
declare fct as a pointer to a function that
returns a void *
expects its first argument is of type pointer to a function that expects a void * and returns a void * and
expects its second argument is of type void *.
void* (*fct)(void*(*)(void*), void*)
// 44444 2111 333333333333333333333333
fct (1) is a pointer (2) to a function (3*) that returns a pointer (4).
(*) The function parameters are void*(*)(void*) and void*
void*(*)(void*) a pointer to a function that takes a pointer argument and returns a pointer
void* a pointer
cdecl.org and my compiler both agree. It's a syntax error. There are more close parentheses than open ones.
A function pointer named x that returns void * and takes two parameters of type void * would look like:
void *(*x)(void *, void *);
Read to the left:
myFuncName is a pointer. What is it a pointer to?
Read to the right:
myFuncName is a pointer to a function which takes two arguments, one of which is a function pointer (with one void* argument and returning void*, similar to myFuncName), and the other one being of type *void*, returning void*. What does the function return?
Read to the left:
myFuncName is a pointer to a function which takes two arguments (see above) and returns void*
As https://stackoverflow.com/users/47453/bill-lynch pointed out, cdecl will tell you the same, as long as your syntax is correct.
Best regards
Andreas

What does method(void * param) mean in C?

I need to know what it means when a function has a void * parameter. For example:
function(void * param){}
It is a function that receives a void*. This may be used to pass any kind of pointer in C.
A good example is the pthread_create function, and the pthread start routine.
Note, however, that if no return type is specified, it defaults to return an int, which it does not in your example.
param is a void pointer means pointer to any data type . You may call generic type pointer.
e.g.
func(void *param)
{
// body
}
call like this :
char* cptr;
int* iptr;
float* fptr;
func(cptr);
func(iptr);
func(fptr);
A void * is a pointer to any data, i.e. to data of an unknown or unspecified type.
param has type void *, which in C serves as a "generic" pointer type; any object pointer type can be converted to void * and vice versa without need for an explicit cast (some implementations allow function pointer types to be converted to void *, but that's not universal and not guaranteed by the language standard).
Note that a void pointer may not be dereferenced, so you can't do something like x = *param in the body of the function. You'd have to convert the pointer to a different type such as int * or double * or whatever to get what it points to. And that depends on what function is supposed to do with it.
It means the param of type void* (reference to a void), which is the size of a memory location . You can reference any memory location with this, which in practice anything.

C - Strange Prototype Argument

What's going on in this function prototype? Obviously the void parameter with some sort of typecasting is confusing...
int *my_func(my_struct *m, void (*m_op)(my_struct *v, void arg));
The second argument to the function my_func is a pointer to a function that returns no value (void), but which takes two arguments, a my_struct pointer and ... and (an invalid) void. The latter should probably be void *arg; you cannot have a variable or argument of type void. As it stands, the code should not compile.
This prototype declares a function, my_func that returns int *. It takes two arguments, the first being of type my_struct * and the second of the strange type void (*)(my_struct *, void). This means that the second argument is a pointer to a function that returns void and takes 2 arguments itself, a pointer to my_struct and void (I assume that was a typo and it takes a void *).
This little article explains how to parse C declarations in a spiral-like motion. Constructing is done in the reverse.
My suggestion - always try to split declarations into smaller ones - in that case code will be more readable. In this case you could re-write code as:
typedef struct {} my_struct;
typedef void (* m_op_function)(my_struct * v, void * arg);
int * my_func(my_struct * m, m_op_function f);
And as everybody said- it's almost 99,99% typo here regarding second parameter to m_op_function- it is possible void* - so that you can pass any pointer to it - be it (char*), (int*), (my_struct*), or anything else. Simply just cast pointer.

How can I typedef a function pointer that takes a function of its own type as an argument?

Example: A function that takes a function (that takes a function (that ...) and an int) and an int.
typedef void(*Func)(void (*)(void (*)(...), int), int);
It explodes recursively where (...). Is there a fundamental reason this can't be done or is there another syntax? It seems to me it should be possible without a cast. I'm really trying to pass a dispatch-table but I could figure that out if I could just pass this one type.
You can wrap the function pointer in a struct:
struct fnptr_struct;
typedef void (*fnptr)(struct fnptr_struct *);
struct fnptr_struct {
fnptr fp;
};
I'm not sure if this is an improvement on casting. I suspect that it's impossible without the struct because C requires types to be defined before they are used and there's no opaque syntax for typedef.
It's impossible to do directly. Your only options are to make the function pointer argument accept unspecified arguments, or to accept a pointer to a structure containing the function pointer, as Dave suggested.
// Define fnptr as a pointer to a function returning void, and which takes one
// argument of type 'pointer to a function returning void and taking
// an unspecified number of parameters of unspecified types'
typedef void (*fnptr)(void (*)());

Resources