I'm looking for answer if presented in a example function cast and call is valid in C(if not any example how to get similiar behavior would be nice).
Example:
#include <stdio.h>
#include <stdint.h>
typedef struct {
uint32_t a;
} parent_t;
typedef struct {
parent_t parent;
uint32_t b;
} child_t;
typedef void (*funct_ptr_t)(parent_t* pParent, uint32_t x);
void test_function(child_t* pChild, uint32_t x);
int main()
{
funct_ptr_t func = (funct_ptr_t)test_function;
funct(NULL, 0U);
return 0;
}
void test_function(child_t* pChild, uint32_t x) {
// do something
}
@EDIT As above turned to be invalid, i would like to also ask about second approach
typedef void (*funct_ptr_t)(void* pChild, uint32_t x);
void test_function(child_t* pChild, uint32_t x);
int main()
{
funct_ptr_t func = (funct_ptr_t)test_function;
child_t child;
func(&child, 0U);
return 0;
}
void test_function(child_t* pChild, uint32_t x) {
// do something
}
CodePudding user response:
This is not valid.
A function can only be called though a compatible function pointer type. For two function pointer types to be compatible, the corresponding arguments must have compatible types and the return types must be compatible.
test_function
has type void (*)(child_t*, uint32_t )
but is being called through a function pointer with type void (*)(parent_t*, uint32_t )
. This means the function is being called through an incompatible type and doing so triggers undefined behavior.
If you're trying to accept a pointer to different types for the first parameter, the simplest way to handle this is to change the type of the first parameter for both the function and function pointer to void *
, then perform the necessary conversion inside of the function.
Another option is to change the type of the first parameter to test_function
to parent_t *
and perform a cast inside the function. This will work because a pointer to a struct can be converted to a pointer to its first member, so you could do this:
void test_function(parent_t* pChild, uint32_t x);
int main()
{
funct_ptr_t func = (funct_ptr_t)test_function;
child_t c;
funct((parent_t *)&c, 0U);
return 0;
}
void test_function(parent_t* p, uint32_t x) {
child_t *p_Child = (p_Child *)p;
// do something
}