2

This question is in reference to the solution/explanation provided here Allocating variable length multi dimensional arrays ( see the accepted answer).

In my case I am using the same function for defining a 3D array like following

void arr_alloc (int x, int y, int z, int(**aptr)[x][y][z])
{
  *aptr = malloc( sizeof(int[x][y][z]) ); // allocate a true 3D array
  assert(*aptr != NULL);
} 

For the codebase I am working on, which is a huge project repository, earlier I was using pointers to pointers to pointers to type (***array) and then interleaving such that I can use it as a 3D (pseudo)array. For this I used to declare the variable as extern int ***array and define the pointer in a separate header file as int ***array. My question - (a) For the new function in place what should be the declaration and definition for the array given that the SO reference answer uses the declaration and definition such as

int x = 2;
int y = 3;
int (*aptr)[x][y];

(b) Incentive of using size_t vs int as the indexing variable given that size_t occupies 8 bytes whereas int occupies 4 bytes.

PS. I checked in gdb the variable type after the declaration and definition line mentioned above (also in the SO answer) which is (int (*)[variable length][variable length][variable length]) 0x0

Edit : Please note that this question is about the declaration and definition of the array / array pointer and not the declaration of the function that allocates and sets up the array in place.

datapanda
  • 437
  • 1
  • 5
  • 12
  • I believe for`(a)`, since arrays decay into pointers in C: `void arr_alloc(int x, int y, int ***aptr);` would work. I am not really sure what you are asking for `(b)`. That said, it has been pointed out to me on occasion that being a 3 star programmer is rarely necessary. – ryyker Apr 19 '18 at 18:44
  • Everything about this code is crazy, including the `assert`. – melpomene Apr 19 '18 at 18:46
  • @ryyker i gues i have edited to make myself clear. the question is about variable declaration not function declaration – datapanda Apr 19 '18 at 18:48
  • @ryyker an array only decays down by one dimension. A two-dimensional array decays into a pointer to the one-dimensional array elements of the outer array. Once this is done it is already a pointer, not an array value, and does not need to decay further. – Alex Celeste Apr 19 '18 at 18:49
  • @melpomene well i kind of adapted to a well written and accepted answe. Indeed people have different styles/ways of coding. if you can comment on "what particularly you found crazy" then this would help me in modifying the implementation for the good. – datapanda Apr 19 '18 at 18:49
  • [Three Star Programmer](http://wiki.c2.com/?ThreeStarProgrammer). Also note that there is no multidimensional arrays in c or c++. Arrays of arrays are not exactly multidimensional arrays. – user7860670 Apr 19 '18 at 18:50

1 Answers1

2

The function declaration is correct for allocating a 3D array. A pointer to such an array would have type int (*)[a][b][c], so the function needs to accept the address of a pointer of that type to write to it, i.e. int (**)[a][b][c], which is what you have.

To use this function you would need to call it as follows:

int s1=2, s2=3, s3=4;
int (*p)[s1][s2][s3];
arr_alloc(s1,s2,s3,&p);

Then you could write to the 3D array like this:

int i,j,k;
int n = 0;
int i,j,k;
int n = 0;
for (i=0;i<s1;i++) {
    for (j=0;j<s2;j++) {
        for (k=0;k<s3;k++) {
            (*p)[i][j][k] = n++;
        }
    }
}

EDIT:

A true multidimensional array must declare a size for all dimensions except for the first. If your array is declared at file scope, that means the size of those dimensions must be compile time constants.

If the dimensions have to vary, you'll need to make it a void * and cast as necessary. You loose some type checking here, but it's the only way to do this:

int s1, s2, s3;
void *arr;

void arr_alloc (int x, int y, int z)
{
  int (*p)[x][y][z] = malloc( sizeof(int[x][y][z]) );
  assert(p != NULL);
  arr = p;
  s1=x;
  s2=y;
  s3=z;
}

int main()
{
    arr_alloc(2,3,4);
    int (*p)[s1][s2][s3] = (int(*)[s1][s2][s3])arr;

    int i,j,k;
    int n = 0;
    for (i=0;i<s1;i++) {
        for (j=0;j<s2;j++) {
            for (k=0;k<s3;k++) {
                    (*p)[i][j][k] = n++;
            }
        }
    }
    for (i=0;i<s1;i++) {
        for (j=0;j<s2;j++) {
            for (k=0;k<s3;k++) {
                    printf("%d:%d:%d=%d\n",i,j,k,(*p)[i][j][k]);
            }
        }
    }
    free(p);
    return 0;
}
dbush
  • 205,898
  • 23
  • 218
  • 273
  • I am following the same in a small test code. In the actual case i want to declare the variable `p or *p or *p[ ][ ][ ]` as an `extern ....`. It is this which I am refering to. How to declare the variable in my case. – datapanda Apr 19 '18 at 19:00
  • A true multidimensional array **must** declare a size for all dimensions except for the first. If your array is declared at file scope, that means the size of those dimensions must be compile time constants. If they have to vary, you're stuck with a staggered array. – dbush Apr 19 '18 at 19:07
  • @datapanda Actully, you could get away with it if you use a `void *`. See my edit. – dbush Apr 19 '18 at 19:16