c++cmultidimensional-arrayc-preprocessorsquare-bracket

How to access 1D arrays with multiple brackets for readability?


I have a huge code using a 3D array managed with pointers. Something like:

int *** tab;
tab = malloc(m*sizeof(int**));
for(i= 1..n) tab[i] = malloc(n*sizeof(int*));  
... etc...

and later the elements are accessed with:

tab[i][j][k] = ...

But because of specific issues with this structure, I would like to declare tab as a contiguous array instead but still use the syntax with 3 brackets in the code. The compiler will internally replace them like this:

tab[i][j][k] = ...  =>  tab[i*m*n+j*m+k] = ...

So the array is accessed with only one pointer dereference. I'd like not to change the source code (no sed).

For example I could do this by declaring tab in stack:

int tab[n][m][l];

but unfortunately this doesn't work if m and n are runtime variables.


Solution

  • In C (C99 or C11), the tab array with variable dimensions can be passed as a function parameter as long as its dimensions are also passed in the preceding parameters. Here is an example to show what I mean:

    #include <stdio.h>
    #include <stdlib.h>
    
    int sum3d(unsigned int dim_n, unsigned int dim_m, unsigned int dim_l,
              int tab[dim_n][dim_m][dim_l])
    {
        int total = 0;
        int n, m, l;
    
        for (n = 0; n < dim_n; n++)
        {
            for (m = 0; m < dim_m; m++)
            {
                for (l = 0; l < dim_l; l++)
                {
                    total += tab[n][m][l];
                }
            }
        }
        return total;
    }
    
    int main(void)
    {
        unsigned int dim_n, dim_m, dim_l;
        unsigned int n, m, l;
        int tot;
    
        dim_n = 10;
        dim_m = 5;
        dim_l = 4;
    
        int (*tab)[dim_m][dim_l] = calloc(dim_n, sizeof(*tab));
        if (!tab)
        {
            fprintf(stderr, "Memory allocation failure!\n");
            exit(1);
        }
        for (n = 0; n < dim_n; n++)
        {
            for (m = 0; m < dim_m; m++)
            {
                for (l = 0; l < dim_l; l++)
                {
                    tab[n][m][l] = 1;
                }
            }
        }
    
        printf("total = %d\n", sum3d(dim_n, dim_m, dim_l, tab));
        return 0;
    }
    

    In function sum3d, tab could have been declared as int tab[][dim_m][dim_l], or as int (*tab)[dim_m][dim_l], omitting the leftmost dimension in both cases.