2

In my function bodies reduce() and initialize(...) I want to work with the array globalArray as a three-dimensional one, where the dimensions are not known until runtime.

How do I cast the globalArray pointer to a variable-length array (pointer) and use it naturally? I think the typedef approach helps, but I'm still lost. This current version compiles and seemingly works after my tinkering. Are Cast #1 and Cast #2 as clear and safe as can be achieved?

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

double * globalArray; /* working from a situation where the array is global, declared elsewhere */
int M, N, P; /*array dimensions not known until runtime */

double reduce();
double reduce()
{
    /* Here I want to re-interpret the one-dimensional globalArray into
       a multi-dimensional variable-length array so that compiler takes
       care of the indexing math for me.*/
    typedef double (*arr_t)[N][P];

    const arr_t castArray = (arr_t)globalArray;  /* Cast #1 */

    double sum=0.0;
    for (int i=0; i<M; i++)
        for (int j=0; j<N; j++)
            for (int k=0; k<P; k++)
                sum += castArray[i][j][k];
    return sum;
}

void initialize(int M, int N, int P, double threedimarray[M][N][P])
{
    for (int i=0; i<M; i++)
        for (int j=0; j<N; j++)
            for (int k=0; k<P; k++)
                threedimarray[i][j][k] = (double)(i*N*P + j*P + k);
}

int main(int argc, char **argv)
{
    M = 10; N=1000; P=200;
    globalArray = malloc( M*N*P* sizeof(double) );

    typedef double (*arr_t)[N][P];
    initialize(M, N, P, (arr_t)globalArray); /* Cast #2 */

    double result = reduce();
    printf("Reduced result: %f\n", result );
    return 0;
}

https://ideone.com/5Y8Q64

I'm reworking a small section of a large program. There are clearly better design approaches than program scope array pointers. It is what it is. From a self-documenting point-of-view, it'd be nice if the solution doesn't throw away the fact that we "know" the extent of the leading dimension (M) as well.

The similar SO questions relating to function argument declarations are helpful but I'm not connecting the dots I guess. I decided to ask here hoping the answer will reach more people.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
NoahR
  • 1,417
  • 3
  • 18
  • 33
  • Did you try: double castArray[M][N][P] = (double[][][])globalArray; ? – VuVirt Sep 26 '17 at 16:06
  • Well, now I have: error: array has incomplete element type 'double []' – NoahR Sep 26 '17 at 16:09
  • You can do it like this, but M, N and P must be const: double(*castArray)[2][2][2] = (double(*)[2][2][2])globalArray; But it is better to access globalArray like this: globalArray[i * M + j * N + k], where 0 <= i < M; 0 <= j < N; 0 <= k < P; – VuVirt Sep 26 '17 at 16:23
  • 1
    The correct expression would be `globalArray[i * N*P + j * P + k]` but that's exactly what I am trying to avoid with C99 variable-length arrays functionality. – NoahR Sep 26 '17 at 16:53

1 Answers1

2

Here's one possible casting solution I've arrived at after some tinkering.

typedef double (*arr_t)[N][P];
arr_t castArray = (arr_t)globalArray;

/* Now castArray can be accessed by multi-dimensional index notation */
castArray[i][j][k] = 3.14;

Downsides:

1) Does not self-document known leading dimension length M.

NoahR
  • 1,417
  • 3
  • 18
  • 33