How to make an array containing function pointers? [duplicate] - c

I've a little question.
I'm trying to define an array of function pointers dynamically with calloc.
But I don't know how to write the syntax.
Thanks a lot.

The type of a function pointer is just like the function declaration, but with "(*)" in place of the function name. So a pointer to:
int foo( int )
would be:
int (*)( int )
In order to name an instance of this type, put the name inside (*), after the star, so:
int (*foo_ptr)( int )
declares a variable called foo_ptr that points to a function of this type.
Arrays follow the normal C syntax of putting the brackets near the variable's identifier, so:
int (*foo_ptr_array[2])( int )
declares a variable called foo_ptr_array which is an array of 2 function pointers.
The syntax can get pretty messy, so it's often easier to make a typedef to the function pointer and then declare an array of those instead:
typedef int (*foo_ptr_t)( int );
foo_ptr_t foo_ptr_array[2];
In either sample you can do things like:
int f1( int );
int f2( int );
foo_ptr_array[0] = f1;
foo_ptr_array[1] = f2;
foo_ptr_array[0]( 1 );
Finally, you can dynamically allocate an array with either of:
int (**a1)( int ) = calloc( 2, sizeof( int (*)( int ) ) );
foo_ptr_t * a2 = calloc( 2, sizeof( foo_ptr_t ) );
Notice the extra * in the first line to declare a1 as a pointer to the function pointer.

I put a small example here that may help you
typedef void (*fp)(int); //Declares a type of a void function that accepts an int
void test(int i)
{
printf("%d", i);
}
int _tmain(int argc, _TCHAR* argv[])
{
fp function_array[10]; //declares the array
function_array[0] = test; //assings a function that implements that signature in the first position
function_array[0](10); //call the cuntion passing 10
}

You'd declare an array of function pointers as
T (*afp[N])();
for some type T. Since you're dynamically allocating the array, you'd do something like
T (**pfp)() = calloc(num_elements, sizeof *pfp);
or
T (**pfp)() = malloc(num_elements * sizeof *pfp);
You'd then call each function as
T x = (*pfp[i])();
or
T x = pfp[i](); // pfp[i] is implicitly dereferenced
If you want to be unorthodox, you can declare a pointer to an array of pointers to functions, and then allocate that as follows:
T (*(*pafp)[N])() = malloc(sizeof *pafp);
although you would have to deference the array pointer when making the call:
x = (*(*pafp)[i])();

typedef R (*fptr)(A1, A2... An);
where R is the return type, A1, A2... An are the argument types.
fptr* arr = calloc(num_of_elements,sizeof(fptr));

Assuming all your functions are of type void ()(void), something like this
typedef void (*fxptr)(void);
fxptr *ptr; // pointer to function pointer
ptr = malloc(100 * sizeof *ptr);
if (ptr) {
ptr[0] = fx0;
ptr[1] = fx1;
/* ... */
ptr[99] = fx100;
/* use "dynamic array" of function pointers */
free(ptr);
}

Related

How to return a 2D array?

I was searching for an efficient way to create a 2D array and return it, usually I make an array of pointers, allocate memory for each pointer, and return an **ptr. I was looking for another way to do it because then I have to free every single memory allocated.
I was reading online that you can allocate a 2D array like this: int (*arr)[n] = malloc( sizeof *arr * i );
In which ptr is a pointer, pointing to the adress of arr[n].
When I try to return arr, from the following function: int *array_of_smallest(int count);
I get: warning: assignment to ‘int *’ from incompatible pointer type ‘int (*)[n]’ [-Wincompatible-pointer-types]
If I initialise another pointer and point it to array, then return it, I'm only returning a 1D array.
I think I'm mixing diferent concepts and confusing myself.
With an array of pointers I don't have a problem, but I wanted a simplier way to create a 2D array, also easier to free, but I'm not being able to return that array from my function.
You declared a pointer of the variable modified type type int ( * )[n].
int (*arr)[n] = malloc( sizeof *arr * i );
That is the variable n used in the declarator is not an integer constant expression.
In this case the function should have the return type void *. And it can be declared like
void * array_of_smallest(int count)
{
int (*arr)[n] = malloc( sizeof *arr * i );
//...
return arr;
}
In the caller you will write
int ( *arr )[n] = array_of_smallest( count );
In this declaration the value of n must be the same as used within the function.
If to use an integer constant expression like
int (*arr)[2] = malloc( sizeof *arr * 2 );
then the function declaration will look like
int ( * array_of_smallest(int count) )[2];
Or you can introduce a typedef name before the function declaration like
typedef int Array[2];
and in this case the function will look like
Array * array_of_smallest(int count);
The fundamental issue with returning the array is that it is not possible to declare Variably-Modified Type (like a pointer to VLA) at the file scope.
The reason of the problem can be explained as follow. Your code behaves more or less like this:
typedef int T[n];
T* array_of_smallest(int count) { ... }
Unfortunately, defining such a type T is not possible because of two reasons:
n is usually not visible at file scope, except if it was a global variable
evaluation of n would require code execution at file scope which is forbidden
Workarounds
Return void* as described in other answer.
Pass a pointer to VLA in "by-reference" style, as a pointer to a pointer to array
void array_of_smallest(int count, int (**p)[n]) {
...
*p = arr;
}
Return a pointer to incomplete array type of int[]. It is not possible to return incomplete types but it is possible to return a pointer to incomplete types:
int (*array_of_smallest(int count))[] { ... }
or a bit cleaner with a help of typeof extension (feature in C23)
typeof(int[]) *array_of_smallest(int count) { ... }
And use it as in the void* case:
int ( *arr )[n] = array_of_smallest( count );
This solution provides type-checking for the element type, however it works only for 2-dimensional arrays.
Wrap the pointer into a structure and use a macro to reconstruct its type on the client side:
typedef struct {
int rows, cols;
void* data;
} Arr2D;
Arr2D array_of_smallest(int count) {
...
return (Arr2D) { .rows = i, .cols = n, .data = arr };
}
#define ARR2D_DEF_VIEW(view, arr2d) int (*view)[(arr2d).cols] = (arr2d).data
... usage ...
Arr2D arr = array_of_smallest(42);
ARR2D_DEF_VIEW(view, arr);
... do stuff with view[i][j]
}
Alternatively, use typeof extension to infer the type of VLA view rather than declare it in a macro:
#define ARR2D_VIEW_TYPE(arr2d) typeof(int(*)[(arr2d).cols])
...
Arr2D arr = array_of_smallest(42);
ARR2D_VIEW_TYPE(arr) view = arr.data;

Return a dynamically allocated array? (C)

Consider the given 2d array allocation:
int (*some)[10] = malloc(sizeof(int[10][10]));
This allocates a 10 x 10 2d array. Apparently its type is int (*)[10]. I want to write a function initialize() that will allocate it, initialize it and then return a pointer to the array, so that the construction some[i][j] would be usable in other functions which can pass a pointer to the array it onto each other.
What should the prototype, specifically the return type of initialize() be?
int (*initialize(void))[10] { ... }
initialize is a function, which takes no parameters and returns a pointer to an array of 10 int.
You should use a typedef for that.
allocates the table of nrow pointers to (allocated) int array of size elements
void *allocate_rows(int *(*ptr)[size], size_t nrows)
{
int (*tmpptr)[size] = *ptr;
*ptr = malloc(nrows * sizeof(*ptr));
if(*ptr)
{
while(nrows--)
{
tmpptr = malloc(sizeof(*tmpptr));
if(!tmpptr)
{
/* malloc failed do something */
}
else
{
tmpptr++;
}
}
return *ptr;
}
In
int (*some)[10] = malloc(sizeof *some);, some is a "pointer to an array of 10 int`.
If you want other to be a function returning a pointer to an array of of 10 int, you can start with int (*some)[10]; and replace some with what a call to a such function would look like to get your declaration.
int (*some)[10]; => int (*other(argument1,argument2))[10];
That's how it worked in pre-standardized C. Since standardized C has prototypes, you'd also replace the argument identifier list with a parameter type list, e.g.:
int (*other(int argument1, double argument2))[10];
The cdecl program or the cdecl website can help you verify the result:
$ echo 'explain int (*other(int,double))[10]'|cdecl
declare other as function (int, double) returning pointer to array 10 of int
Most people find typedefs more readable:
typedef int (*pointer_to_an_array_of_10_int)[10];
pointer_to_an_array_of_10_int other(int, double);
//to verify it's a compatible declaration
int (*other(int , double ))[10];

Acessing a 2D array inside a function

I have a function which accepts int* pInput[] as an argument.
void Process(int* pInput[], unsigned int num);
I have to call this function via 2 methods as
main()
{
int *pIn[2];
int input[2][100] = {0};
pIn[0] = ( int* )malloc( 100 * sizeof( int) );
pIn[1] = ( int* )malloc( 100 * sizeof( int) );
Process( pIn, 2 );
Process( ( int** )input, 2 );
}
Then how can i access each value of pInput inside function 'Process'?I cannot access it directly as pIn[0][0].
how can i access each value of pInput inside function 'Process'?I cannot access it directly as pIn[0][0].
No! You can access it exactly that way: pInput[0][0] if the input you pass is pIn. This is because pIn is an array of int*s I.e. it's of type int *[n] each of its element pointing to an array of ints. It would decay into int**.
However, if you want to pass input, a 2D array of ints, you've to do more since a 2D array doesn't decay into a double pointer, T** but into a pointer to an array, T (*) [n]. This is because array decay is not recursive, it happens only to the first level. Alternatively, you can do this (Live example)
pIn[0] = input[0];
pIn[1] = input[1];
and now pass pIn to Process. Here pIn is a surrogate for input and it needs to have as many elements as input, which is not a very elegant solution. A better way to pass input, when you know the dimensions during compile-time is
void Process(int (*pInput)[100], size_t rows) { }
void Process(int input [2][100], size_t rows) { }
/* These two are the same; the compiler never sees the `2`. input's type is int(*)[100] */
Read on array decay to understand the situation better.
Aside
Do I cast the result of malloc? No, you do not need to cast the return value of malloc in C.
What should main() return in C and C++? The return type of main should be int.
Related
C-FAQ: My compiler complained when I passed a two-dimensional array to a function expecting a pointer to a pointer.
What is array decaying?
Why can we omit the first dimension of a multidimensional array when we are passing it to a function
In your process() function you just need to access it normally like any 2d array as below. Calling both ways are same.
void Process( int * pInput[], unsigned int num)
{
printf(" %d", pInput[0][0]); //printing value of pInput[0]
printf(" %d", pInput[1][0]); //printing value of pInput[1]
pInput[0][0] = 8054; // changing its value.
pInput[1][0] = 8055; // changing its value.
}
int main()
{
int *pIn[2];
int input[2][100] = {0};
pIn[0] = ( int* )malloc( 100 * sizeof( int) );
pIn[1] = ( int* )malloc( 100 * sizeof( int) );
// assigning value to array.
pIn[0][0] = 23;
pIn[0][1] = 2;
pIn[1][0] = 5689;
pIn[1][1] = 5643;
Process( pIn, 2 ); //calling process funtion
printf(" %d", pIn[1][0]); //printing the changed value by process funtion.
}
You are getting confused because you are using different types when there's no need for such. Arrays follow the same rules of indirection as any other type. If you would allocate a plain int dynamically, you would write int* x = malloc(sizeof(*x));. Simply do the very same thing when it comes to arrays. Don't confuse things by mixing in the "arrays decay to pointers" rule.
So we have int input[2][100], very straight-forward, it is a plain 2D array. Now if you want to allocate that dynamically, you will need a pointer to such an array:
int (*pIn)[2][100]; // pointer to an array of int [2][100].
pIn = malloc(sizeof(*pIn));
And the whole program would then be:
#include <stdlib.h>
void Process (size_t num, int pInput[num][100])
{
}
int main (void)
{
int (*pIn)[2][100];
int input[2][100] = {0};
pIn = malloc(sizeof(*pIn));
if(pIn == NULL)
{
// error handling
return 0;
}
Process(2, *pIn);
Process(2, input);
free(pIn);
return 0;
}
Comments:
size_t is the most correct type to use for array sizes, as it is the type returned by the sizeof operator. So it is just an unsigned integer with a fancy name.
int pInput[num][100] in the function will actually decay into an array pointer to an array of 100 int. You don't need to know that to use it though, simply use pInput[x][y] and pretend it is a 2D array. The important thing here is to understand that the array is not passed by value.
The correct form of main is int main (void).
Casting the result of malloc is pointless.
Always check the result of malloc and remember to clean up allocated data.

Making int foo(int bar[][N]) work with int ** baz

I have a function with the following prototype:
int foo(int bar[][N]);
And I want to send to it the variable int ** baz which is an array of the same size, only it was allocated.
I tried to explicitly cast and call foo() like so: foo((int(*)[N])baz); and it silenced the errors from the compiler but all the values in baz became junk when in foo() (why did it happen btw?).
Is there a way to do this without duplicating the same function and changing it's prototype?
baz was allocated like so:
int ** baz = (int**)malloc(N*sizeof(int*));
for (i = 0; i < N; i++)
baz[i] = (int*)malloc(N*sizeof(int));
Allocate baz like
int ( *baz )[N] = malloc( N * N * sizeof( int ) );
In this case there is no problem to call function
int foo(int bar[][N]);
with argument baz.
Taking into account your comment then the function that allocates a two-dimensional array dynamically and returns a pointer to it can look like
#include <stdio.h>
#include <stdlib.h>
#define N 10
typedef int ( *PTR )[N];
PTR allocate( int n );
int ( *allocate( int n ) )[N]
{
int ( *p )[N] = malloc( n * sizeof( *p ) );
return p;
}
int main( int argc, char * argv[] )
{
free( allocate( N ) );
return 0;
}
I showed two ways of the declaration of the function.
The type int ** is not compatible with the type int (*)[N] (which is what the type of your function argument resolves to). The former is a pointer to pointer to int. The latter is a pointer to an array of N ints.
It is very important to understand at this point that arrays are not pointers. An array is a contiguous block of some number of elements of the same type. In most contexts, including when they appear as function arguments, the values of expressions having array type are automatically converted to pointers (to the array's first element), but that's a whole different thing than array objects being pointers. This distinction is a frequent source of confusion, but it is essential to understand when an array is a member of an aggregate type, such as a structure, union, or higher-dimensional array.
If you want to dynamically allocate an M x N array that you can pass to your function, then that looks like this:
int (*baz)[N] = malloc(M * sizeof(*baz));
If you want to pass your existing pointer pointer to your function, then the function should have this prototype:
int foo(int **bar);

How to declare a pointer to : array of void pointers? in c

I'm little bit confused about how to declare a pointer to array or void*.
let say :
void* myarr[20];
how to declare a pointer to "myarr?"
I think you mean a pointer to the first element of an array of pointers to void.
It is simply to do if you will use the following general approach. Let's assume that you have an array of some type T
T myarr[20];
then the definition of the pointer to the first element of the array will look like
T *ptr = myarr;
Now all what you need is substitute T for you particulat type and you will get
void * myarr[20];
void * *ptr = myarr;
If you mean indeed a pointer to the array then approach is the following
T myarr[20];
T ( *ptr )[20] = &myarr;
Or if to substitute T for void * you will get
void * myarr[20];
void * ( *ptr )[20] = &myarr;
typedef void *myarr_t[20];
myarr_t *ptr_to_myarr;
void* (*myarr_ptr)[20] = myarr_ptr;
here is my test code:
#include <stdio.h>
int main()
{
int* myarr[20];
int * (*myarr_ptr)[20] = myarr;
printf("%p %p\n", myarr, *myarr_ptr);
return 0;
}
$ ./a.out
0x7fff8bd39dd0 0x7fff8bd39dd0
void** ptrToArrary = myarr_t; //pointing to base address of array.

Resources