Is it possible to create statically in C a 2d array of pointers to 2d arrays, like:
#define m 4
#define n 4
#define p 2
#define q 2
char arr1[m][n] = {{0}};
char arr2[m][n] = {{0}};
char (*parr[m][n])[p][q] = {{&arr1, 0, &arr2, 0}};
int main() {
return 0;
}
The 2d array of pointers parr
is sparse, with some values to 0 (NULL), which is why I don’t want to use a 4d array in the first place.
This compiles, but I get the following warning:
warning: initialization from incompatible pointer type
With the following command:
gcc -Wall -Wextra -pedantic -std=c99 test.c
What is wrong?
The problem is that when you declare pointers, arrays and array pointers, the [] takes precedence over * unless you add parenthesis. This is why you declare an array pointer as (*parr)[]
rather than *parr[]
, since the latter gives an array of pointers instead.
Similarly, when declaring a pointer to a 2D array, you would type (*parr)[m][n]
. So it seems logical that an array of 2D-array pointers should be declared as ((*parr)[m][n])[p][q])
. But the outer parenthesis here actually does nothing, that expression is equivalent to (*parr)[m][n][p][q]
. And that’s an array pointer to a 4D array! Which is why you get compiler warnings.
Now what you actually want is to get an array of array pointers to 2D arrays, is something like char (*parr[p][q])[m][n]
. Which looks rather insane, nobody will understand a declaration like that.
The only sane way to write code like this is through typedefs:
typedef char arr_t[m][n];
arr_t arr1 = {{0}};
arr_t arr2 = {{0}};
arr_t* parr[p][q] =
{
{&arr1, 0},
{&arr2, 0}
};
I think what you meant to do is the following:
char arr1[m][n] = {{0}};
char arr2[m][n] = {{0}};
typedef char (*some_type)[n]; // type of arr1 and arr2
some_type parr[p][q] = {{arr1, NULL}, {arr2, NULL}}; //array containing arr1 and arr2
You can then access parr
e.g by
printf("%cn", parr[0][0][0][0]);
which will print arr1[0][0]
.
Here would be my solution — i prefer using static 1D arrays rather than static 2D arrays due pointer arithmetic (i like to keep things simple):
PS. i would suggestin using m!=n and p!=q for testing, so you can catch possible indexing errors!
#include <stdio.h>
#define m 4
#define n 4
#define p 2
#define q 2
char arr1[m*n] = {0};
char arr2[m*n] = {0};
typedef char array_2d[m][n];
char* parr[p][q] = { {(char*)arr1, NULL}, { (char*)arr2, NULL} };
int main()
{
for (int i = 0; i < m; i ++ )
for (int j = 0; j < n; j ++ )
{
arr1[i*n + j] = i + j;
arr2[i*n + j] = i - j;
}
for (int i = 0; i < m; i ++ )
{
for (int j = 0; j < n; j ++ )
{
char* arr1_ptr = parr[0][0];
char* arr2_ptr = parr[1][0];
printf("%d", (int)(arr1_ptr[i*n + j] - arr2_ptr[i*n + j] ));
}
printf("n");
}
return 0;
}
In the declaration of parr I think you meant to use p and q as its dimensions:
$ cat test.c
#include <stdio.h>
#define m 4
#define n 4
#define p 2
#define q 2
char arr1[m][n] = {{0}};
char arr2[m][n] = {{0}};
char (*parr[p][q])[m][n] = {{&arr1, NULL}, {&arr2, NULL}};
int main(void)
{
printf("%dn", (*parr[0][0])[0][0]);
return 0;
}
This compiles cleanly with GCC 4.8.2:
$ gcc --version
gcc (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc -ansi -fsanitize=address -g -pedantic -Wall -Wextra -Wfatal-errors -Wno-unused-parameter -o test test.c
$