1

I'm trying to pass an three dimensional array to a function like this:

void example( double*** bar ) {
    // Stuff
}

int main() {
    double[3][2][3] foo;
    // Initialize foo
    example( foo );
    return 0;
}

This causes the gcc to give me "Invalid pointer type". How am I supposed to be doing this? I could just make the entire argument a one-dimensional array and arrange my data to fit with that, but is there a more elegant solution to this?

edit:

In addition, I can't always specify the length of each sub-array, because they may be different sizes. e.g.:

int* foo[] = { { 3, 2, 1 }, { 2, 1 }, { 1 } };

If it helps at all, I'm trying to batch pass inputs for Neurons in a Neural Network. Each Neuron has a different number of inputs.

murphy2902
  • 67
  • 6
  • About the second part of your question: You can create a function `void example(int *bar[])` and pass `foo`, but correctly processing `bar` is just as difficult as correctly processing `foo`. One simple solution would be including a "stop marker" in the array, e.g. `int* foo[] = { { 3, 2, 1, -1 }, { 2, 1, -1 }, { 1, -1 }, { -2 } };` (but please replace the magic numbers with symbolic constants!) – Erich Kitzmueller May 04 '15 at 19:28
  • How do you tell the length of each sub-array if they're of different lengths? – Jonathan Leffler May 04 '15 at 19:34
  • You just process the sub-arrays till you hit -1; there is no way to directly get the length of the sub-arrays, since that information is simply not available at runtime, C doesn't keep it anywhere. – Erich Kitzmueller May 04 '15 at 19:40
  • I have it stored myself. Each neuron keeps the number of inputs it's expecting, so I use that. The function that handles all of this works, theoretically, I just need to figure out how to correctly make a double*** – murphy2902 May 04 '15 at 19:47
  • See [this answer of mine](http://stackoverflow.com/questions/30023867/how-can-i-work-with-dynamically-allocated-arbitrary-dimensional-arrays/30023868#30023868) for a structure that encapsulates the dimensions and can be passed to functions. – luser droog May 05 '15 at 04:35

4 Answers4

3

just use double*. A multidimensional array is stored contiguously in memory so you are quite welcome to give it your own stride. This is how bitmaps are passed on OpenGL.

doron
  • 27,972
  • 12
  • 65
  • 103
  • Could I cast this into a multidimensional array within the function? – murphy2902 May 04 '15 at 19:18
  • Nothing to stop you. The only thing is that you will probably lose the ability to determine the various dimensions at runtime. It is probably a much better idea to do your own stride calculations. That way the sizing of the x,y,z dimensions can all be done at runtime. – doron May 06 '15 at 16:34
  • I've done a lot of testing, and I think this is the one that works the best for me. Thanks! – murphy2902 May 17 '15 at 22:42
2

A one-dimensional int array decays into an int pointer when passing it to a function. A multi-dimensional array decays into a pointer to an array of the next lowest dimension, which is

void example(double (*bar)[2][3]);

This syntax can be a bit baffling, so you might chose the equivalent syntax:

void example(double bar[][2][3]) {
    // Stuff
}

int main() {
    double foo[3][2][3];

    example(foo);
    return 0;
}

The first dimension does not have to be given, it's that part that is "decaying". (Note that the dimensions of arrays are not given on the type as in Java, but on the array name.)

This syntax works for variable-length arrays (VLAs) as well, as long as you pass the dimensions before the array:

void example(int x, int y, double (*bar)[x][y]) {
    // Stuff
}

int main() {
    double foo[3][2][3];

    example(2, 3, foo);
    return 0;
}

This feature requires C99 and is not compatible with C++.

M Oehm
  • 28,726
  • 3
  • 31
  • 42
  • This is really informative! Unfortunately, I didn't explain that each sub-array may be a different length as well. I've edited the question to include that. – murphy2902 May 04 '15 at 19:25
1

If the array size is fixed, you can use:

void example(double bar[][2][3]) {

}

Otherwise, you can pass the size along with the array into the function:

void example(size_t x, size_t y, size_t z, double bar[x][y][z]) {

}
user12205
  • 2,684
  • 1
  • 20
  • 40
0

That can't be done in C the way you're thinking of. If you need a function that operates on variable-size multidimensional arrays, you'll either have to pass the sizes (all but one) explicitly to the function, or make a structure and pass that. I generally always make a structure when a 2D or 3D array is called for, even if they're of fixed size. I think it's just cleaner that way, since the structure documents itself.

Lee Daniel Crocker
  • 12,927
  • 3
  • 29
  • 55
  • I've been thinking about this as well. I may try this as well as a single-dimensional array, and see which one is easier to use. – murphy2902 May 04 '15 at 19:26