SedriX
SedriX

Reputation: 510

Determine the type of an array which stores the pointer to other arrays of different dimensions

I have many constant 2D arrays of all possible permutation of integer in [0,LEN) for many LEN:

static const char permu2[][2] = {{0, 1}, {1, 0}};
static const char permu3[][3] = {{0, 1, 2}, {0, 2, 1}, {1, 0, 2},
                                {1, 2, 0}, {2, 0, 1}, {2, 1, 0}};
static const char permu4[][4] = {
    {0, 1, 2, 3}, {0, 1, 3, 2}, {0, 2, 1, 3}, {0, 2, 3, 1}, {0, 3, 1, 2},
    {0, 3, 2, 1}, {1, 0, 2, 3}, {1, 0, 3, 2}, {1, 2, 0, 3}, {1, 2, 3, 0},
    {1, 3, 0, 2}, {1, 3, 2, 0}, {2, 0, 1, 3}, {2, 0, 3, 1}, {2, 1, 0, 3},
    {2, 1, 3, 0}, {2, 3, 0, 1}, {2, 3, 1, 0}, {3, 0, 1, 2}, {3, 0, 2, 1},
    {3, 1, 0, 2}, {3, 1, 2, 0}, {3, 2, 0, 1}, {3, 2, 1, 0}};
static const char permu5[][5] = {{0, 1, 2, 3, 4}, {0, 1, 2, 4, 3}, {0, 1, 3, 2, 4}, /*... */}
// and many more as you can imagine...

And I'd like to store the pointers to those arrays in another array:

static const char *permu[] = {0,      0,      permu2, permu3, permu4,
                             permu5, permu6, permu7, permu8};
static const int fac_seq[] = {1,   1,    2,     6,      24,      120,
                              720, 5040, 40320, 362880, 3628800, 39916800};

So that for a given LEN=n, I can access those constants in this way:

const int n = 8;
for ( size_t i = 0; i < fac_seq[n]; i++ ) {
    for ( size_t j = 0; j < n; j++ ) {
        printf( "%2d", *( permu[n] + n*i  + j ) );
    }
    putchar( '\n' );
}

Although this will compile and work correctly, the compiler (gcc) complains like:

30.c:1966:47: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
 static const char *permu[] = {0,      0,      permu2, permu3, permu4,
                                               ^~~~~~
30.c:1966:47: note: (near initialization for ‘permu[2]’)
30.c:1966:55: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
 static const char *permu[] = {0,      0,      permu2, permu3, permu4,
                                                       ^~~~~~
30.c:1966:55: note: (near initialization for ‘permu[3]’)

What should be the right type for the permu array? I tried const char **permu[] and still got the same warnings.

Upvotes: 2

Views: 57

Answers (2)

HTNW
HTNW

Reputation: 29193

The correct declaration is

static const char (*permu[9])[] = {0,      0,      permu2, permu3, permu4,
                                   permu5, permu6, permu7, permu8};

permu is an array of 9 pointers to arrays of unknown numbers of const chars. Writing the 9 is optional; it can be inferred from the initializer. You could instead make it an array of pointers to void, as in the other answer, but it's best to preserve as much information as possible. You use it like this:

const int n = 4;
const char (*perms)[n] = permu[n];
for (size_t i = 0; i < fac_seq[n]; i++) {
    for (size_t j = 0; j < n; j++) {
        printf("%2d", perms[i][j]);
    }
    putchar('\n');
}

Note that I perform a cast with the assignment to perms. I take a pointer to an array of unknown size and convert it to a pointer where the array size is actually n. This is what allows the double [] syntax later: the type const char[n] has a defined size (sizeof(char)*n), so we know how far we need to skip for perms[i].

Godbolt

Upvotes: 1

Weather Vane
Weather Vane

Reputation: 34583

You could try

static const void *permu[] = { };

You would then have to cast it when accessed.

Alternatively you can make each array one-dimensional and work out the indexing yourself.

Upvotes: 1

Related Questions