0

I need explanation for following code:

int a[2][3][2] = { 1,2,3,
                   4,5,6,
                   7,8,9,
                   10,11,12 };
std::cout << a[0][5][0];

As far as multi dimensional arrays are concerned, first index indicates row count, second index indicates column count and third index indicates array count. But, here this code gives me 11 as the output, moreover what's more shocking is

for(int i=0; i<12; i++)
    std::cout<<a[0][0][i];

prints all the elements of the array. I couldn't find explanation for this kind of access any where on the web. Somebody please clarify me!

2
  • Arrays are laid out in contiguous memory. I think this is technically undefined behaviour, but it's do heavily relied on to do anything except this. Commented Nov 16, 2013 at 20:40
  • Think about the memory layout of a multidimensional array. Is int a[2][3][2] different than int a[12]? Commented Nov 16, 2013 at 20:40

4 Answers 4

1

Think about it like this.

a[2][3][2] is really just a[12] grouped into groups of 2 then 3.

a[0][5][0] is really a[0][0][5*2] = a[0][0][10]

This is because an array is loaded into contiguous memory.

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

3 Comments

a[0][0][5*2] != a[10] since a[10] decays into a bidimensional array
Thanks for catching that. A little ahead of myself there
ok, that makes some sense. then, how is a[1][0][0] is converted ?
1

The results you expect only hold as long as you are within the bounds of a[2][3][2]. That is, when you do a[0][0][0] up to a[1][2][1], your assumptions will hold. But once you cross that boundary, the results you see are no longer the same.

What is actually happening here is that a[i][j][k] is technically the same as k+j*2+i*2*3 elements after the first, considering the numbers you used in your code. This makes it possible to have a representation of your array that looks "3D" but actually in memory they are "in line" or in a one-dimensional array. So by doing this *2 and *2*3 you are actually jumping to the "next" sub-array.

Why doesn't it work when you get out of the bounds of a[2][3][2]? Take for example for a[i][j][k] with k=4, it will be equivalent to i*2*3 + j*2 + k = i*2 + (j+1)*3 + 1. So it's as if it had "jumped" to the next row/column/whatever.

You can visualize this better on a 2-dimensional array by imagining a table and going through the row and once you beyond the last column of the row, you fall on the row below it.

However, C does not warn you when you go out of the bounds of your multidimensional array, or when you "fall" off the row you're on.

Update

You are right in saying a[0][5][0] does not exist. What happens in this case is that you will actually read something else which is in memory, right next to a. So for example, let's say you have a and b in your code, when you are dealing with a and b in your code, what is going on under the hood is that a and b are just some chunk of memory. And let's say a is an array with 12 elements in total, when you get outside of these 12 elements, C will just assume the array is as big as you say it is, and go fetch the piece of memory that's after 15 "chunks" and will give it to you. So a[15] actually exists but it does not belong to the array. It might belong to b if they are next to each other on memory or it can belong to something else entirely.

The technical terminology is that when you declare a as an array of size 12 integers, it will allocate the memory of 12 integers (12 * 4 bytes) next to each other and label that as a for you. a will point to the beginning of that piece of memory; it's a pointer. When you do a[x] or a[i][j][k] you will get a pointer to the x-th piece of memory of a. And if x is greater than 12, it'll go outside of a and grab whatever was lying there and consider it is an integer. (while it could be something else; that's why you might get garbage when you do this kind of thing, because it might actually be something else and they interpret it as if it was an integer).

5 Comments

May I know where from did you get this knowledge? I didn't find this information anywhere on the web or in any book. I've several unanswered questions with me, I just want to have some knowledge base in hand.
according to your explanation a[0][5][0] should become a(0+5*3+0*2*3) which is equal to a[15] which does not exist.
I learned this in class. C/C++ is the only language I did not manage to learn online on my own so far. Regarding a[0][5][0], I'll update my post now.
no, I was just saying you should change k+j*3+i*2*3 statement to k+j*2+i*2*3
Oh I thought you were asking what happens for a[15].. :)
0

The moral of the story is ... "There is no spoon" (Matrix).

There are no rows, columns and pages. just a memory with linear sequence, where elements are stored just one after the other.

Multidimensional arrays are just a "projection" and the idea or pages / rows / cols is just an abstraction.

a[k][j][i] simply means (indirection levels apart) *(a + k*Y*X + j*X + i)

where Z,X and Y are the sizes of the dimensions. What we most likely call "pages", "rows" and "columns".

Note that. independently of Z,Y and X, putting k=0, j=0, i=11, in the equivalent expression makes perfectly sense, and will refer to the 12 value.

Comments

0

Multidimensional arrays are stored in memory in a continuos memory location, so your array looks in memory like:

1 2 3 4 5 6 7 8 9 10 11 12

As C provides no way of array bound check, you can access memory after the limit of the array, even unallocated memory (this would yeld sometimes to errors).

The access a[x][y][z] is computed using x, y, z, values and the size of the array a in a memory adress relative to a (as you might know, a is a pointer to the first element in the array, a[0][0][0], in this case).

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.