Function Pointers Casting in C - c

Why do i need to remove the function pointer casting to use the function as shown below ?
This Compiles:
#include <stdio.h>
int print_int(int i){
printf("%d", i);
return i;
}
typedef int (*print_int_func) (int);
int main(){
void** p = malloc(1*sizeof(print_int_func*));
p[0] = (print_int_func*)print_int;
((print_int_func)p[0])(2); // This Compiles
((print_int_func*)p[0])(2); // This does NOT
return 0;
}

The declaration typedef int (*print_int_func) (int); declares print_int_func to be a pointer to a specific type of function. So (print_int_func)p[0] casts p[0] to such a pointer to a function, but (print_int_func*)p[0] casts p[0] to a pointer to a pointer to a function. Thus, the result is a pointer to an object (that object being a pointer to a function). Since it is an object, not a function (or pointer to a function), it cannot be called like a function.
Additionally, avoid using void * for pointers to functions. void * is a pointer to an object, and the C standard does not define conversions between pointers to objects and pointers to functions. To create a “generic” pointer to a function, simply choose any function type and use a pointer to that type:
Convert to the chosen type when storing the pointer.
Convert to the actual function type when calling the function type.
For example, you can declare an arbitrary type:
typedef void (*CommonFunctionPointer)(void);
and make an array of them:
CommonFunctionPointer *p = malloc(N * sizeof *p);,
and then you can store any function pointer in the array:
p[i] = (CommonFunctionPointer) print_int;
and use a pointer from the array by casting it back to its correct type:
((int (*)(int)) p[i])(2);.

Related

How to access elements of an array of function pointers using another pointer and in turn call one of the functions?

Suppose I declare an array of function pointers as follows:
typedef void (*ptr[4])( int a, int b)={fn1,fn2,fn3,fn4};
Now i declare,
ptr *ptr_to_fn_arr;
The question is, how do I call any of the functions( fn1,fn2,fn3,fn4) using the pointer variable ptr_to_fn_arr?
typedef is used to create an alias name for other data type and you cannot initialize a type.
So, this is wrong:
typedef void (*ptr[4])( int a, int b)={fn1,fn2,fn3,fn4};
^^^^^^^^^^^^^^^^^
Instead you should do:
typedef void (*ptr[4])( int a, int b);
This will creates ptr as a type for array of 4 function pointers that takes two int type as argument and does not return any value.
Now using this alias name ptr you can create variable of its type, like this:
ptr x = {fn1, fn2, fn3, fn4};
This will initialize variable x which is an array of 4 function pointers of type ptr.
You can call it like this:
x[0](1, 2); // this is equivalent to fn1(1, 2)
x[1](1, 2); // this is equivalent to fn2(1, 2)
....
.... and so on.
But the statement
ptr x = ...
Just by looking at it, it doesn't seems that x is an array until you look into the ptr typedef.
So, for better readability you can do:
typedef void (*ptr)( int a, int b);
This will creates ptr as a type for function pointer that takes two int type as argument and does not return any value.
Now to create the array of 4 function pointers of type ptr, you can do:
ptr x[4] = {fn1, fn2, fn3, fn4};
Call it in similar way:
x[2](1, 2); // this is equivalent to fn3(1, 2)
It'll be easier to do this if we have the typedef be to the function pointer type:
typedef void (*fptr)(int, int);
Now fptr is a typedef for "pointer to function accepting two ints and returning void".
So declaring the array is simple:
fptr fn_arr[4] = {fn1, fn2, fn3, fn4};
And declaring the pointer is simple:
fptr *ptr_to_fn_arr = fn_arr;
But now how do we call the functions?
fn_arr is an array of function pointers, so fn_arr[i] is a function pointer.
ptr_to_fn_arr is a pointer to a function pointers, so *ptr_to_fn_arr is a function pointer. So is ptr_to_fn_arr[i]. (The analogies here to more "ordinary" arrays and pointers should be obvious.)
So the strictly-interpreted way to call via ptr_to_fn_arr would be
(*(*ptr_to_fn_arr))(1, 2)
or
(*ptr_to_fn_arr[i])(3, 4)
But since the only thing you can do with a function pointer is call the pointed-to function, you don't actually need the explicit *, so both of these would work, too:
(*ptr_to_fn_arr)(1, 2)
or
ptr_to_fn_arr[i](3, 4)

what this (int**)&p; mean in the statement?

This code is practice code for pointers. But I am not understanding the (int**)&p; means in this code.
void fun(void *p);
int i;
int main()
{
void *vptr;
vptr = &i;
fun(vptr);
return 0;
}
void fun(void *p)
{
int **q;
q = (int**)&p;
printf("%d\n", **q);
}
Please elaborate how it is evaluated.
It's a type cast, that interprets the value of &p, which has type void **, as instead having type int ** which is the type of the variable the value is stored in.
The cast is necessary, since void ** is not the same as void * and does not automatically convert to/from other (data) pointer types. This can be confusing.
&p being of type void**, is being casted to type of int** which is to be assigned to q.
SIDE-NOTE : "Any pointer can be assigned to a pointer to void. It can then be cast back to its original
pointer type. When this happens the value will be equal to the original pointer value."
Be careful when using pointers to void. If you cast an arbitrary
pointer to a pointer to void, there is nothing preventing you from
casting it to a different pointer type.

What is the use of void** as an argument in a function?

I have to implement a wrapper for malloc called mymalloc with the following signature:
void mymalloc(int size, void ** ptr)
Is the void** needed so that no type casting will be needed in the main program and the ownership of the correct pointer (without type cast) remains in main().
void mymalloc(int size, void ** ptr)
{
*ptr = malloc(size) ;
}
main()
{
int *x;
mymalloc(4,&x); // do we need to type-cast it again?
// How does the pointer mechanism work here?
}
Now, will the pointer being passed need to be type-cast again, or will it get type-cast implicitly?
I do not understand how this works.
malloc returns a void*. For your function, the user is expected to create their own, local void* variable first, and give you a pointer to it; your function is then expected to populate that variable. Hence you have an extra pointer in the signature, a dereference in your function, and an address-of operator in the client code.
The archetypal pattern is this:
void do_work_and_populate(T * result)
{
*result = the_fruits_of_my_labour;
}
int main()
{
T data; // uninitialized!
do_work_and_populate(&data); // pass address of destination
// now "data" is ready
}
For your usage example, substitute T = void *, and the fruits of your labour are the results of malloc (plus checking).
However, note that an int* isn't the same as a void*, so you cannot just pass the address of x off as the address of a void pointer. Instead, you need:
void * p;
my_malloc(&p);
int * x = p; // conversion is OK
Contrary to void *, the type void ** is not a generic pointer type so you need to cast before the assignment if the type is different.
void ** ptr
Here, "ptr" is a pointer to a pointer, and can be treated as a pointer to an array of pointers. Since your result is stored there (nothing returned from mymalloc), you need to clarify what you wish to allocate into "ptr". The argument "size" is not a sufficient description.

How do I specifiy the return type for an array of pointers to void?

I want to return an array of pointers to void. How do I specify this in the function prototype?
int*[] func();
Functions cannot return array types. You can either return a pointer to the first element of the array (type void **), or you can return a pointer to the whole array (type void (*)[N]). Note that the address value is the same either way (the address of the first element of the array is also the address of the array), it's just a difference in types.
To return a pointer to a SIZE-element array of pointer to void, the function signature would be
void *(*func())[SIZE]
which breaks down as
func -- func
func() -- is a function
*func() -- returning a pointer
(*func())[SIZE] -- to a SIZE-element array
*(*func())[SIZE] -- of pointer
void *(*func())[SIZE] -- to void.
Remember that postfix operators such as [] and () have higher precedence than unary operators such as *, so *a[] is an array of pointer and (*a)[] is a pointer to an array.
For C89 and earlier, SIZE must be a compile-time constant expression. For C99 you can use a variable expression.
Whatever you do, don't try to return a pointer to an array that's local to the function, such as
void *(*func())[SIZE]
{
void *foo[SIZE];
...
return &foo;
}
or
void **func()
{
void *foo[SIZE];
...
return foo;
}
Once the function exits, foo ceases to exist, and the pointer value returned no longer points anywhere meaningful. You're either going to have to declare the array as static in your function, or you're going to have to dynamically allocate it:
void *(*func())[SIZE]
{
void *(*foo)[SIZE] = malloc(sizeof *foo);
...
return foo;
}
or
void **func()
{
void **foo = malloc(sizeof *foo * SIZE);
...
return foo;
}
As other people stated you can't really do this because arrays will degrade to pointers. the standard way to do this is to return a struct
struct array {
void* ptrs[5];
}
then your procedure would be declared like
struct array foo() {...}
Example:
void **function(int c)
{
void **arrayOfVoidStars = (void **)malloc(c*sizeof(void *));
/* fill the array */
return arrayOfVoidStars;
}

What type does & return for an Array Parameter inside a C Function?

When passing an Array Argument to a Function, it's memory address is copied into an Array Parameter. Because of this:
sizeof() returns the size of the entire array for the Array Argument (inside caller)
sizeof() returns the size of a pointer for the Array Parameter (inside called Function)
My question is, what type is the Array Parameter inside the Function? And more specifically, what type is returned when using the & Operator on an Array Parameter? It's not a Pointer to Array of Type, nor is it a Pointer to Type, as shown in this code (labeled BAD):
void doSomething(int arrayParam[10]);
int main()
{
int array[10] = { 0 };
int (*arrayPtr)[] = &array; // OK
printf("%p\n", array); // 0x7fff5fbff790
doSomething(array);
return 0;
}
void doSomething(int arrayParam[10])
{
printf("%p\n", arrayParam); // 0x7fff5fbff790
int (*arrayPtr)[] = &arrayParam; // BAD: Initialization from incompatible pointer type
int * element0Ptr = &arrayParam; // BAD: Initialization from incompatible pointer type
element0Ptr = arrayParam; // OK
element0Ptr = &arrayParam[0]; // OK
}
Thanks for any help you can offer! :)
Most of the time, when you use an array, it decays to a pointer to its initial element. So, if you have:
void f(int* x);
int array[10];
int* initial_element_of_array = array; // array decays to a pointer to initial element
f(array); // same here
f() gets a pointer to the initial element of array.
Something that is rather confusing at first is that if a function has a parameter that is of an array type (like if you had void f(int x[])), this is actually converted such that it is exactly the same as void f(int* x). There is no difference between them: array type parameters are the same as pointer type parameters.
Once you pass an array to a function, all you have is a pointer to its initial element, so if you apply the & operator to the int*, you get an int** (a pointer to an int*).

Resources