2

I just learned about variable length arrays in C, and somebody suggested to me that I can realize a 3D array-like object in C simply as a pointer to a variable length array. A simple implementation would look as follows:

#include <stdio.h>
#include <stdlib.h>

int main( int argc, char *argv[] ) {

    size_t  ii, jj, kk,
            Nx, Ny, Nz;

    Nx  = 2;
    Ny  = 3;
    Nz  = 4;

    // initialize 3D array as pointer to a variable length array
    double (*arr3d)[Ny][Nz] = calloc(Nx, sizeof *arr3d);

    for( ii=0 ; ii<Nx ; ++ii )
        for( jj=0 ; jj<Ny ; ++jj )
            for( kk=0 ; kk<Nz ; ++kk )
                printf( "arr3d[%ld,%ld,%ld] = %f, address = %p\n",
                    ii, jj, kk, arr3d[ii][jj][kk], &arr3d[ii][jj][kk] );

    free(arr3d);
    return 0;

}

In my understanding, one advantage (besides of the one-line implementation) is that arr3d can be simply passed to a function,

int doSomething( size_t dim1, size_t dim2, size_t dim3, double arr3d[dim1][dim2][dim3] );

by calling this function in the main function as follows:

doSomething( Nx, Ny, Nz, arr3d );

My question now, is this a valid implementation of a 3D array-like object or will I run into some trouble ? Note that in the actual case, the dimensions are larger by roughly a factor of 1000 each.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Alf
  • 1,821
  • 3
  • 30
  • 48

1 Answers1

2

If you have an array like

double a[Nx][Ny][Nz];

then you may write

double (*arr3d)[Ny][Nz]  = a;

that is the pointer arr3d points to the first element of the array a that has the type double{Nt][Nz].

So this memory allocation

double (*arr3d)[Ny][Nz] = calloc(Nx, sizeof *arr3d);

is correct. There is in fact allocated dynamically a thre-dimensional array and the pointer arr3d points to the first element of the array.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Thanks for the explanation! I just realized, I haven't checked for errors, that would probably be a simple `if (arr3d == NULL)` after the `calloc`, correct? – Alf Jan 26 '22 at 17:25
  • 1
    @Alf Yes you need to check whether a memory was successfully allocated. – Vlad from Moscow Jan 26 '22 at 17:26
  • Is it correct that just using the definition of `a` as you have written it in the beginning (i.e. without the pointer), so just using a VLA for the 3D array, has the problem that `a` is defined on the _stack_ and therefore much more limited in size, or is that a misinterpretation of mine....? – Alf Jan 27 '22 at 06:19
  • 1
    @Alf yes. Definition `double a[Nx][Ny][Nz];` creates an VLA with *automatic* storage, usually taken from limited stack. Automatic VLAs are usually bad idea, prefer dynamic ones allocated with malloc/calloc – tstanisl Jan 27 '22 at 06:50