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);
Related
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;
Let's say I have multiple (a variable number) of 2D arrays (which may even be variable-length):
int a[2][2] = {{1,2},{3,4}};
int b[2][2] = {{5,6},{7,8}};
...
which I now want to pass to a function. I do not want to copy the 2D arrays into 3D array. However, I want to specify the bounds so that the function knows the dimensions of the 2D arrays so that I can index them conveniently with [i][j]
How can I format the functions' signature so that it accepts a pointer to an array (of unknown length) which contains 2D arrays of which it does now the dimensions?
E.g. something like
void myfunc(int[][3] *test, int len)
though of course this is syntactically invalid. Is specifying the bounds of arrays inside an array (passed by pointer) impossible in C? Will I be forced to move a and b into pointers, or forced to copy them into a 3D array?
If your compiler supports a variable length arrays you can write
void myfunc( int rows, int cols, int a[rows][cols] );
Take into account that the third parameter is implicitly converted to the type int ( * )[cols], that is within a function you are dealing with a pointer to one dimensional array. Nevertheless you can use expressions like
for ( int i = 0; i < rows; i++ )
{
for ( int j = 0; j < cols; j++ ) a[i][j] = value;
}
Otherwise if the compiler does not support variable length arrays and the second dimension of all arrays is the same then the function can be declared like
void myfunc( int ( *a )[2], int rows );
Take into account that this declaration
int[][3] *test
in any case is incorrect.
If you want to pass several two-dimensional arrays then you can within main declare a one dimensional array like
int a[2][2] = {{1,2},{3,4}};
int b[2][2] = {{5,6},{7,8}};
//...
int ( *p[] )[2] = { a, b, /*...*/ };
and then pass it to a function.
In this case the function will look like
void myfunc( int ( **p )[2], size_t n );
Here is a demonstrative program
#include <stdio.h>
void myfunc( int ( **p )[2], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
for ( size_t j = 0; j < 2; j++ )
{
for ( size_t k = 0; k < 2; k++ ) printf( "%d ", p[i][j][k] );
putchar( '\n' );
}
putchar( '\n' );
}
}
int main(void)
{
int a[2][2] = {{1,2},{3,4}};
int b[2][2] = {{5,6},{7,8}};
int ( *p[] )[2] = { a, b };
myfunc( p, sizeof( p ) / sizeof( *p ) );
return 0;
}
Its output is
1 2
3 4
5 6
7 8
If the first dimension of the arrays is not fixed and varies then you could pass also to the function an array of first dimensions of the arrays
If you have two things you need to pass to a function, you either
pass two separate arguments; or
create some kind of data structure that contains (pointers to) said things, and pass (a pointer to) that.
It doesn't matter if your things are arrays or anything else.
The same thing holds when you have a variable number of things. You can pass a variable number of arguments to a function, but that's a separate topic, so let's concentrate in option 2. In this case your data structure should be an array of pointers to things.
OK so how do you create one when your thing has a complex type, like an array (of arrays of pointers to functions that return a pointer to an array, or whatever)? The answer is simple: use a typedef.
typedef int MyThing[2][2]; // could be anything
MyThing one = {{1,2},{3,4}};
MyThing two = ...; // etc
MyThing* manyPointersToThings[] = {&one, &two};
void myFunc(int nThings, MyThing things[nThings]) {
// in here, each things[i] is a *pointer* to MyThing
(*things[0])[1][2] = 42;
// whatever
}
This works for any kind of thing. If your thing is in fact an array, there is another option: your data structure could store pointers to first elements of your arrays, rather than pointers to arrays themselves.
typedef int MyThing[2]; // this type names an *element* of your array
MyThing one[2] = {{1,2},{3,4}};
MyThing two[2] = ...; // etc
MyThing* manyPointersToThings[] = {one, two}; // note no & here
void myFunc(int nThings, MyThing things[nThings]) {
// in here, each things[i] is a pointer to the first element of an array
things[0][1][2] = 42;
// whatever
}
With this option, you gain some flexibility, as your arrays need not all be of the same size. You also lose that ugly dereference in parentheses.
For completeness, here are prototypes of the same functions sans typedef:
void myFunc(int nThings, int (*things[nThings])[2][2]) // version 1
void myFunc(int nThings, int (*things[nThings])[2]) // version 2
These are a bit more flexible than typedef versions, because now you can use a variable (another parameter) instead of the hardcoded number 2.
If you have trouble writing down things like the above, try this.
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);
}
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.
Given the following code:
void
foo( int* array )
{
// ...
}
void
bar( int** matrix )
{
// ...
}
int
main( void ) {
int array[ 10 ];
int matrix[ 10 ][ 10 ];
foo( array );
bar( matrix );
return 0;
}
I don't understand why I get this warning:
warning: passing argument 1 of ‘bar’ from incompatible pointer type
Although 'foo' call seems to be ok.
Thanks :)
Well, it's certainly not well understood by the C community as can be seen by glancing over SO. The magic is, all of the following are totally, 100%, equivalent:
void foo(int (*array)[10]);
void foo(int array[][10]);
void foo(int array[10][10]);
void foo(int array[42][10]);
It is very important to draw the distinction of a pointer and an array. An array is not a pointer. An array can be converted to a pointer to its first element. If you have a pointer you have this:
--------
| ptr | -------> data
--------
However, if you have an array, you have this:
---------------------------
| c1 | c2 | c3 | ... | cn |
---------------------------
With the pointer, the data is at a whole other planet, but linked to by the pointer. An array has the data itself. Now, a multi-dimensional array is just an array of arrays. The arrays are nested into a parent array. So, the sizeof of your array is:
(sizeof(int) * 10) * 10
That is because you have 10 arrays, all of which are arrays of 10 integers. Now, if you want to pass that array, it is converted. But to what? A pointer to its first element. The element type is not a pointer, but an array. As a consequence, you pass a pointer to an array of 10 int:
int (*)[10] // a pointer to an int[10]
It is neither a array of int*, nor a int**. You may ask why the array is not passed as an int**. It's because the compiler has to know the row-length. If you do an array[1][0], the compiler will address a place sizeof(int) * 10 bytes apart from the begin of the 2 dimensional array. It decodes that information in the pointer-to-array type.
So, you have to chose among one of the above fully equivalent function prototypes. Naturally, the last one is just confusing. The compiler just silently ignores any number written in the most outer dimension if a parameter is declared to be an array. So i would also not use the second last version. Best is to use the first or second version. What is important to remember is that C has no (real) array parameters! The parameter will be a pointer in the end (pointer to array in this case).
Note how the multi-dimensional case of above is similar to the degenerate, one dimensional case below. All of the following 4 versions are fully equivalent:
void foo(int *array);
void foo(int array[]);
void foo(int array[10]);
void foo(int array[42]);
Passing multi-dimensional arrays in C is a tricky subject. See this FAQ.
The question to ask is how you'll be using bar. If you always know it will be passed a 10x10 array then rewrite it as
bar(int matrix[10][10]);
If you want to cope with arrays of varying dimensions then you might have to pass in the lengths:
bar(int *matrix, int width, int height);
The problem is that the data structure matrix[10][10] is actually not a table of ten pointers to array[10]'s, but it is an sequential array of 100 integers. The proper signature for bar is
bar (int matrix[10][10])
If you actually want to represent the matrix using indirection and have int **matrix as the parameter type for bar, then you need to allocate it differently:
int *matrix[10];
int my_data[100];
int i;
for (i = 0; i < 10; i++) { matrix[i] = &(my_data[i * 10]); }
bar(matrix);
Now 'matrix' matches the type int **. 'matrix' is an array of ten pointers, and you can pass it by pointer, hence getting the second *.
Here is some code to practice on - it contains all possible types of passing 2dimensional array and code to access element values
#include <stdio.h>
#define NUMROWS 2
#define NUMCOLUMNS 5
#define FILL_ARRAY() \
*array[0] = '1'; \
(*array)[7] = '2'; \
*(array[1]) = '3'; \
*(*(array+1)+1) = '4'; \
*(array[0]+3) = '5'; \
*(*array+2) = '7'; \
array[0][1] = '6';
void multi_01( char (*array)[NUMCOLUMNS] ) { FILL_ARRAY(); }
void multi_02( char array[][NUMCOLUMNS] ) { FILL_ARRAY(); }
void multi_03( char array[NUMROWS][NUMCOLUMNS] ) { FILL_ARRAY(); }
void multi_04( char **array ) { FILL_ARRAY(); }
void multi_05( char *array[] ) { FILL_ARRAY(); }
void multi_06( char *array[NUMCOLUMNS] ) { FILL_ARRAY(); }
int main(int argc, char **argv)
{
int i;
char mystr[NUMROWS][NUMCOLUMNS] = { { 'X', 'X', 'X', 'X'}, {'X','X','X'} };
char *pmystr[sizeof(mystr)/sizeof(*mystr)];
int numcolumns = sizeof(*mystr);
int numrows = sizeof(mystr)/sizeof(*mystr);
for( i=0; i<numrows; i++ ) pmystr[i] = *(mystr+i);
multi_01( mystr ); multi_02( mystr ); multi_03( mystr );
multi_04( pmystr ); multi_05( pmystr ); multi_06( pmystr );
printf("array '%s', '%s'\n", mystr[0], mystr[1]);
getc(stdin);
return 0;
}
You should define bar as:
bar( int* matrix )
In C all arrays should be passed as int* (or type_of_element* for other types).
int ** would be ok if your data was really an array of pointers. int[*data[] for example. Thats what you get in main(int argc, char *argv[]).
int **matrix
would indicate that you have a pointer to a pointer to int. That's commonly used to indicate a pointer to an array of pointers (also called a vector). That's definitely NOT the case with
int matrix[10][10]
which is a more of a pointer to a single section of memory sized for 10x10 ints. Try changing to:
void bar(int *matrix[])