I've been wondering for some time what the best way to pass a 2d array to functions is. I know that arrays, passed to functions, decay into pointers, so int arr[25]
would become int *arr
inside a function. The problem is with 2d arrays, int arr[5][5]
would not become int **arr
. Instead I've been taught to pass it like this: int (*arr)[5]
. The problem with that is that the final square brackets need to have a size parameter inside and it needs to be known at compile time.
I've looked around and found this answer which, I believe, has the best solution. The idea is to pass the 2 dimensions separately and the location of the data. So, the function's signature would be like this:
void print(void *arr, size_t rows, size_t cols);
Then, we create a temporary array, which we can use conventionally, like this:
int (*temp)[cols] = (int (*)[cols]) arr;
I wrote some code to test this and it works.
#include <stdio.h>
void fill(void * arr, size_t rows, size_t cols, int val);
void print(void * arr, size_t rows, size_t cols);
int main(void) {
size_t iArr = 5, jArr = 3;
int arr[iArr][jArr];
fill(arr, iArr, jArr, 0x45);
print(arr, iArr, jArr);
return 0;
}
void fill(void * arr, size_t rows, size_t cols, int val)
{
int (*temp)[cols] = (int (*)[cols])arr;
for(size_t i = 0; i < rows; i++)
{
for(size_t j = 0; j < cols; j++)
{
temp[i][j] = val;
}
}
arr = temp;
}
void print(void * arr, size_t rows, size_t cols)
{
int (*temp)[cols] = (int (*)[cols])arr;
for(size_t i = 0; i < rows; i++)
{
for(size_t j = 0; j < cols; j++)
{
printf("%3d ", temp[i][j]);
}
putchar('\n');
}
}
This can also be tested here. I'm curious whether this will work always without errors. I tested it with all kinds of sizes and, again, no problem there. Can this be improved further? Could there be any edge cases where this breaks (checks for valid arguments or making sure the size passed doesn't exceed the stack size are omitted here, as that's not the point of this question).
size_t length = sizeof(array) / sizeof(array[0]);
\$\endgroup\$void print(void *arr, size_t rows, size_t cols);
It is much easier (and less error prone) to use:void print( size_t rows, size_t cols, int arr[ rows ][ cols ] )
Note: the compiler really needs to know the type of each element in the array \$\endgroup\$