2

Is there a way to find the details of a multi-dimensional array? I.E. a[5][3][6]

I was wanting to be able to have it passed to a function for some basic operations on the contents but have the option of feeding the function one, two and three Dim arrays. This way I could reduce my code to just adding in additional loops for doing extra columns.

I've seen code for finding the length of an array but it was only for singles. I would presume that if I was to do a sizeof() type call it would give me the whole total, where I'm needing a column/row breakdown.

Chef Flambe
  • 885
  • 2
  • 15
  • 35
  • 2
    A function receiving an array is not able to determine its size. No matter to which dimension it has been declared. Please see here: http://stackoverflow.com/q/1975128/694576 – alk Aug 02 '14 at 08:20
  • 2
    @alk: However note that such array has to be passed as effectively e.g. `int (*a)[3][6]` as only left-most size can be omitted. – Grzegorz Szpetkowski Aug 02 '14 at 08:47

2 Answers2

6

Multidimensional arrays in C are just arrays-of-arrays, since that you can check sizeof between each sub-array like that:

#include <stdio.h>

int main(void)
{
    int a[5][3][6];
    int dimx, dimy, dimz;

    dimx = (int) (sizeof a / sizeof a[0]);
    dimy = (int) (sizeof a[0] / sizeof a[0][0]);
    dimz = (int) (sizeof a[0][0] / sizeof a[0][0][0]);

    printf("dimx = %d, dimy = %d, dimz = %d\n", dimx, dimy, dimz);

    return 0;
}

Result:

dimx = 5, dimy = 3, dimz = 6

Note that sizeof operator returns result as of type size_t, so it might be better to cast its results (in order to avoid e.g. warning by -Wconversion flag in GCC). You might also want to create function-like macros if you like e.g.:

#define ARRAY_SIZE_3D_X(a) ((int) (sizeof a / sizeof a[0])
#define ARRAY_SIZE_3D_Y(a) ((int) (sizeof a[0] / sizeof a[0][0])
#define ARRAY_SIZE_3D_Z(a) ((int) (sizeof a[0][0] / sizeof a[0][0][0])

Edit:

As pointed by @pmg if you prefer size_t type directly, then use the following instead:

#include <stdio.h>

int main(void)
{
    int a[5][3][6];
    size_t dimx, dimy, dimz;

    dimx = sizeof a / sizeof a[0];
    dimy = sizeof a[0] / sizeof a[0][0];
    dimz = sizeof a[0][0] / sizeof a[0][0][0];

#if __STDC_VERSION__ >= 199901L
    printf("dimx = %zu, dimy = %zu, dimz = %zu\n", dimx, dimy, dimz);
#else
    printf("dimx = %lu, dimy = %lu, dimz = %lu\n", (unsigned long) dimx,
           (unsigned long) dimy, (unsigned long) dimz);
#endif

    return 0;
}

Note that due usual arithmetic conversions it's problematic to mix signed and unsigned values in single expression (e.g. int and unsigned long), as if unsigned type has rank that is greater or equal than signed type, then signed value is promoted to unsigned, e.g. -5 is now some large integer.

Grzegorz Szpetkowski
  • 36,988
  • 6
  • 90
  • 137
  • Good answer :-) out of curiousity: why not use `count()`? Performance? – peter_the_oak Aug 02 '14 at 07:58
  • 3
    @peter_the_oak: AFAIK C language does not have `count()` function (like in C++). As least there is no reference on it in both C99/C11 drafts. – Grzegorz Szpetkowski Aug 02 '14 at 08:07
  • 1
    You could declare `dimx`, `dimy`, `dimz` as `size_t` and, in C99, print the values with `"%zu"` (pre-C99 you need to cast the values and print with eg `"%lu"`) -- and get rid of the ugly unnecessary casts in the assignments. – pmg Aug 02 '14 at 08:12
  • So I understand how you're going about determining the size, really quite simple once I see it spelled out. However as Emmet and alk have pointed out, its a pointer that's being passed to the function so this method won't work(?) inside my function but only in my main. – Chef Flambe Aug 02 '14 at 20:56
  • 1
    @ChefFlambe: That's right, there are several approaches here e.g. you can pass these dimensions as additional function's arguments (as three integers or maybe as struct with them). OTOH as I wrote in comment above essentially such multidimensional array has to be passed as `int (*a)[3][6]` type, so only `5` could be omitted. Of course this completely depends on how you like to pass an array to function, and how was allocated (compile-time on stack, with `malloc`, `alloca`, VLA, etc.). – Grzegorz Szpetkowski Aug 02 '14 at 21:20
3

There is essentially no useful way of determining the dimensions of variable-size arrays passed to functions. Array names passed as parameters decay into pointers and sizeof within a function will just give you the size of the pointer of the corresponding type rather than the size of the original array.

It is somewhat easier to accommodate arrays of variable number of dimensions and size if you represent your multidimensional array in the “canonical” way used in HPC (where you use a 1D array and do index computations yourself), described in this post, but you are still left with the issue of sizes, which you can either pass as additional integer arguments to your function, or you can package everything up in a struct, e.g.:

typedef struct {
    int *data;
    int nx;
    int ny;
    int nz;
} matrix3;

The index computations and memory allocation for the usual way of handling dense 3D matrices are described in detail in the aforementioned post.

Community
  • 1
  • 1
Emmet
  • 6,192
  • 26
  • 39