views:

676

answers:

5

How do you initialize a 3d array in C++

int min[1][1][1] = {100, { 100, {100}}}; //this is not the way
+21  A: 

The array in your question has only one element, so you only need one value to completely initialise it. You need three sets of braces, one for each dimension of the array.

int min[1][1][1] = {{{100}}};

A clearer example might be:

int arr[2][3][4] = { { {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4} },
                     { {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4} } };

As you can see, there are two groups, each containing three groups of 4 numbers.

Carl Norum
Yes, yes of course you're right, these several D arrays keeps eluding me...
Chris_45
Does that work in C?
miguelSantirso
Yes that will work in C as well.
nthrgeek
You don't *need* nested braces for a multidimensional array. The standard requires that you can just run the values together in a flat list.
Potatoswatter
As long as you don't care about warnings: `warning: missing braces around initializer (near initialization for 'min[0]')`
Carl Norum
+1  A: 

Maybe you want an array of 3D points? An array of 3D points is not the same as a 3D array.

struct Point3D
{
    int x;
    int y;
    int z;
};

Point3D points[4] = {
    {101, 102, 103},
    {201, 202, 203},
    {301, 302, 303},
    {401, 402, 403}
};
Emile Cormier
Why the downvote? Since the OP used the phrase "3D array", I thought perhaps we has confusing 3D arrays with arrays of 3D data. The OP also tried to initialize his array with 3 values.
Emile Cormier
+1  A: 

Instead of static multidimensional arrays you should probably use one-dimensional array and calculate the index by multiplication. E.g.

class Array3D {
    size_t m_width, m_height;
    std::vector<int> m_data;
  public:
    Array3D(size_t x, size_t y, size_t z, int init = 0):
      m_width(x), m_height(y), m_data(x*y*z, init)
    {}
    int& operator()(size_t x, size_t y, size_t z) {
        return m_data.at(x + y * m_width + z * m_width * m_height);
    }
};

// Usage:
Array3D arr(10, 15, 20, 100); // 10x15x20 array initialized with value 100
arr(8, 12, 17) = 3;

std::vector allocates the storage dynamically, which is a good thing because the stack space is often very limited and 3D arrays easily use a lot of space. Wrapping it in a class like that also makes passing the array (by copy or by reference) to other functions trivial, while doing any passing of multidimensional static arrays is very problematic.

The above code is simply an example and it could be optimized and made more complete. There also certainly are existing implementations of this in various libraries, but I don't know of any.

Tronic
For existing libraries, there is Boost.MultiArray and Boost.uBlas (www.boost.org). The latter is more tailored to linear algebra. Think of Boost as an extension of the standard C++ library (or "The Stuff They Left Out of the Language and Standard Library(TM)").
Emile Cormier
For the anonymous cowards who downvoted, please explain how you can use a c-style multi-dimensional array allocated on the heap. Or how do you avoid stack overflows with large data sets. I think Tronic's advise is useful.
Emile Cormier
@Emile: I didn't downvote, but `new int[2][3][4]` would do the trick. As for @Tronic's code, it just duplicates the effort of `std::valarray`.
Potatoswatter
std::vector is essentially a nice RAII wrapper for new[]/delete[] (and it also does a few other things) so I always prefer it over managing the memory manually. Granted, here it wastes a few bytes for keeping track of the container size, but on the other hand you can use that to calculate the 3D array dimensions. I don't see what std::valarray has to do with this, as I haven't defined any arithmetic operations for the array and valarray doesn't know how to appear as a multidimensional array.
Tronic
@Potatoswatter: In my comment, I forgot to add "...with dimensions only known at runtime". Wait, that still doesn't make sense. I'll just shut up now. :-)
Emile Cormier
@Tronic: You get multidimensional access to a `std::valarray` by subscripting with a `std::gslice`. See the link at my answer. What do you mean, haven't defined any arithmetic operations for the array?
Potatoswatter
A: 

Everyone seems to forget std::valarray. It's the STL template for flat multidimensional arrays, and indexing and slicing them.

http://www.cplusplus.com/reference/std/valarray/

No static initialization, but is that really essential?

Potatoswatter
Your comments/answer made me spawn a question on std::valarray: http://stackoverflow.com/questions/2187648/how-can-i-use-a-stdvalarray-to-store-manipulate-a-2d-array
Emile Cormier
A: 

Here's another way to dynamically allocate a 3D array in C++.

int dimX = 100; int dimY = 100; int dimZ = 100;
int*** array;    // 3D array definition;
// begin memory allocation
array = new int**[dimX];
for(int x = 0; x < dimX; ++x) {
    array[x] = new int*[dimY];
    for(int y = 0; y < dimY; ++y) {
        array[x][y] = new int[dimZ];
        for(int z = 0; z < dimZ; ++z) { // initialize the values to whatever you want the default to be
            array[x][y][z] = 0;
        }
    }
}
KennyCason