1

In the following code,

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

I get output as, 6 and 11.

How is it indexing an element out of its range?

eg- here the sizes are, depth= 3 col=2 row=2 , In thet case arr[0][0][5] means 5th row, which doesnt exist! Can anyone throw light on this.

Mat
  • 202,337
  • 40
  • 393
  • 406
user835194
  • 81
  • 2

3 Answers3

3

Technically, you are invoking undefined behaviour.*

But, most likely, what's happening is that the compiler is calculating the address to read as:

(int *)arr + x*(2*2) + y*2 + z

because your 3D array is really stored in memory as a contiguous linear array.

So in your [0][0][5] case, it's simply reading the (0*4+0*2+5)=5th element (zero-based) of that linear array, which is 6.

Similarly for [1][3][0], it's reading the (1*4+3*2+0)=10th element, which is 11.

* This was discussed in a question I asked: One-dimensional access to a multidimensional array: well-defined C?.

Community
  • 1
  • 1
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • 1
    it's x*(2*2) not x*(2+2)... It's happen to work cause both are 4, but the math is wrong. – Roee Gavirel Sep 11 '11 at 12:44
  • @Roee: Good spot. Fixed now. – Oliver Charlesworth Sep 11 '11 at 12:46
  • +1, in C++, one can say the following well-defined thing instead: `(arr[0][0]+2+2+1)[0]` and `(arr[1]+2+1)[0][0]`. That is, never crossing past-the-end, but making a break at past-the-end, and then moving forward. In C, this is not allowed either. – Johannes Schaub - litb Sep 11 '11 at 13:13
  • @Johannes: Which aspect of C++ allows this? IMO, `arr[0][0]+k` (for `k>2`) is addressing beyond the one-past-the-end element. – Oliver Charlesworth Sep 11 '11 at 13:27
  • @Oli we never did it for `k>2`, that is the trick. When we did `arr[0][0]+2`, we made a pointer that points to `arr[1][0]`, from which place we can add again. C++ does not forbid us to dereference the past the end pointer (as opposed to C) and it does not forbid us to add something to the past the end pointer. In other words, the past the end pointer can alias a pointer to a different object. From which we start again and can add `2`. It would be undefined behavior if we add `3`, instead of doing `2+1`. In this case, parens are important: `+(2+1)` will be UB, but `+2+1` will not be. – Johannes Schaub - litb Sep 11 '11 at 13:35
1

Remember the last time you had a C-style string that you forgot to terminate?

char str[] = {'a','b','c'};
cout << str;

Remember how you printed "abc" then any random gubbins in memory after it because the program kept reading past the array?

It'll do that; it'll just keep going and pull out whatever happens to be there, even though doing so is undefined. The compiler simply doesn't need to warn you about this; you are supposed to figure it out for yourself.

In your case, the data for the next row probably happens to be in memory at that spot.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0

It's like that:

int arr[depth][col][row];
int temp = arr[x][y][z];

then temp = arr[x * (col * row) + y * row + z]

Roee Gavirel
  • 18,955
  • 12
  • 67
  • 94