0

I always thought that x[i] is equivalent to *(x+i). So that would x[i][j] is equivalent to *(*(x+i)+j), which is in this case implies that a 2D array must be implemented as an array of pointers, each of these pointers has to be dereferenced.

But I learned that you can create a 2D array on the heap this way :

char (*arr)[256]=malloc(512*256);

If the former hypothesis is right, then arr[i][j] would access an unauthorized location (since we are dereferencing two times).

Is my former hypothesis wrong in case of 2d arrays ?

user2370139
  • 1,297
  • 1
  • 11
  • 13
  • 8
    2D arrays such as `int a[3][4];` are not arrays of pointers - there are no pointers involved at all. They are arrays of arrays. –  Apr 18 '17 at 13:48
  • A "2d-array" is simply an array of arrays. Try drawing one out on paper and you will see that it all fits together as it should, even when using pointer arithmetic. – Some programmer dude Apr 18 '17 at 13:50
  • some good reading: http://stackoverflow.com/questions/2565039/how-are-multi-dimensional-arrays-formatted-in-memory – NathanOliver Apr 18 '17 at 13:50
  • I see. I understand the array of arrays things, but wouldn't the solution of "array of pointers" have been a perfectly correct way of implementing 2D arrays, plus it is more consistent with the definition of [] ? – user2370139 Apr 18 '17 at 13:56
  • One of the primary tenets of arrays is that they are *contiguous* in memory. Therefore it follows that an array of arrays simple can not be an array of pointers (because then it's no longer contiguous). – Some programmer dude Apr 18 '17 at 14:05
  • Also, if you're to lazy to draw it out yourself, I have done it in [this old answer of mine](http://stackoverflow.com/questions/18440205/casting-void-to-2d-array-of-int-c/18440456#18440456). There you can very easily see the difference between an array of arrays, and an array of pointers. – Some programmer dude Apr 18 '17 at 14:09
  • @NathanOliver: Actually when dereferencing an array or doing arithmetic on an array, **there are pointers involved**. Dereferencing and arithmetic cannot be done on an array. In fact there are exactly four operations on arrays: `&`, `sizeof`, `alignof` and conversion to a pointer to the first element. **Not more**. The latter is implicit for all operators than the listed. – too honest for this site Apr 18 '17 at 14:09
  • @user2370139: An array of pointers is **not** a 2D array and cannot represent one! Read **and think about** my comment above! – too honest for this site Apr 18 '17 at 14:11
  • The array has fixed size objects. What you may be missing is that you need to know at least the first dimension, in order to locate any index. – Kenny Ostrom Apr 18 '17 at 14:12
  • @Olaf Miss ping? I don't think I said anything that contradicts what you said. – NathanOliver Apr 18 '17 at 14:17
  • @NathanOliver: Yes, sorry. Darn auto-completion :-) – too honest for this site Apr 18 '17 at 14:24
  • @NeilButterworth: [this comment](http://stackoverflow.com/questions/43474058/is-the-meaning-of-context-specific?noredirect=1#comment74004016_43474058) was for you actually. – too honest for this site Apr 18 '17 at 14:25

1 Answers1

1
  • x[i] is indeed equivalent to *(x+i). Pointer arithmetic is used in the latter form.
  • In case of a 2D array type array[x][y];, then you have to apply the above rule in several steps.
  • array when used in an expression, decays to a pointer to the first element, in this case of type type(*)[y] - an array pointer pointing at the first array in the array of arrays. Do not confuse an array pointer with "an array of pointers", which means something different entirely.
  • Therefore array + i performs pointer arithmetic on such an array pointer. *(array + i) gives the pointed-at item, a 1D array.
  • If you for some reason unknown want to access an individual item in the 2D array by using pointer arithmetic only, you would therefore have to write something obscure like this:

    *( *(array + i) + j)
    

If the former hypothesis is right, then arr[i][j] would access an unauthorized location (since we are dereferencing two times).

Well, it wasn't right. When you have an array pointer such as char (*arr)[256], then you can access the items as arr[i][j]. Note that arr[i] performs the same kind of pointer arithmetic, so you get "the char[256] array number i". And in that array you then access item j.

This is actually the reason why this syntax is used. Had you written the malloc more type correct like this:

char (*arr)[512][256]=malloc( sizeof(char[512][256]) );

then you would have to de-reference the array pointer before using it, (*arr)[i][j] or otherwise you would get pointer arithmetic on whole 2D arrays.


The question Correctly allocating multi-dimensional arrays explains and illustrates the differences between look-up tables based on arrays of pointers and true multi-dimensional arrays.

Community
  • 1
  • 1
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Thanks for the details I got it now, my misunderstanding was that I always thought that when you do char arr[m][n]; arr is treated as char**, so it is an array of pointers with [] doing pointer arithmetic on a single char, which seems a reasonable way of implementing a 2D array. – user2370139 Apr 19 '17 at 09:05
  • @user2370139 Arrays and pointers are distinct types. It is just that arrays decay into a pointer to the first element whenever they are used in an expression. – Lundin Apr 19 '17 at 11:12