2

What is the best way to pass three dimensional arrays into functions in C?

0

4 Answers 4

5

typedef is your friend.

#include <stdio.h>
typedef int dimension1[20]; /* define dimension1 as array of 20
                               elements of type int */
typedef dimension1 dimension2[10]; /* define dimension2 as array of 10
                                      elements of type dimension1 */

int foo(dimension2 arr[], size_t siz);

int main(void) {
  dimension2 dimension3[7] = {0}; /* declare dimension3 as an array of 7
                                     elements of type dimension2 */
  dimension3[4][3][2] = 9999;
  dimension3[4][0][12] = 1;
  dimension3[3][8][18] = 42;

  printf("%d\n", foo(dimension3, 7));

  return 0;
}

int foo(dimension2 arr[], size_t siz) {
  int d1, d2, d3;
  int retval = 0;
  for (d3=0; d3<siz; d3++) {
    for (d2=0; d2<sizeof *arr / sizeof **arr; d2++) {
      for (d1=0; d1<sizeof **arr / sizeof ***arr; d1++) {
        retval += arr[d3][d2][d1];
      }
    }
    /* edit: previous answer used definite types for the sizeof argument */
    //for (d2=0; d2<sizeof (dimension2) / sizeof (dimension1); d2++) {
    //  for (d1=0; d1<sizeof (dimension1) / sizeof (int); d1++) {
    //    retval += arr[d3][d2][d1];
    //  }
    //}
  }
  return retval;
}

Edit

I don't like the use of definite types as the argument to sizeof.
I added the way to get the sizes of the (sub-)arrays without directly specifying their types, but rather let the compiler infer the right type from the object definitions.


2nd Edit

As Per Eckman notes typedef-ing "bare" arrays can be dangerous. Note that in the code above, I'm not passing arrays themselves to the function foo. I am passing a pointer to a "lower level" array.

foo(), in the code above, accepts a pointer to an object of type dimension2. The dimension3 object is an array of elements of dimension2 type, not an object of dimension3 type (which isn't even defined).

But remember Per Eckman's note.

Sign up to request clarification or add additional context in comments.

Comments

5

It is required you have all but the left-most dimension to be defined at compile time.

#define DIM 5

void do_something(float array[][DIM][DIM])
{
    array[0][0][0] = 0;
    ...
}

Comments

4

Pass them as pointers.

Example

int a[N][M][P];

foo( &a[0][0][0]);

where foo is

void foo( int*)

You might need to pass the dimensions as well, so in such case you might need:

void foo( int*, int D1, int D2, int D3)

and call

foo( &a[0][0][0], N, M, P);

3 Comments

Is the [0][0][0] necessary there?
@Cory, yes it first gets at the first int, and takes it address. That gives the resulting expression type int* instead of array pointer like int(*)[N][M][P]. This is a good hack in my opinion, it can improve program clarity by not having to deal with constants everywhere. But it's formally not guaranteed to work, so use it with care (not sure what could go wrong though).
@Cory, alternative ways to write that are &***a, a[0][0] and **a.
3

typedef-ing "bare" arrays can be dangerous.

Try this

#include <stdio.h>

typedef char t1[10];

void foo(t1 a) {
        t1 b;

        printf("%d %d\n", sizeof a, sizeof b);
}

int main(void) {
        t1 a;
        foo(a);
        return 0;
}

One would think that sizeof two variables of the same type would return the same size but not in this case. For this reason it's a good practice to wrap typedef-ed arrays in a struct.

typedef struct {
        char x[10];
} t1;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.