Pointers and arrays are fundamentally different, especially wrt. to their behavior with sizeof()
and wrt. what they allocate. However, they can sometimes be used interchangeably, because both essentially represent an address.
If you dynamically allocate memory, you will receive a pointer, which points to the beginning of a chunk of memory. If you allocate memory of a size that represents a multiple of a type's size, it should be intuitively clear that you can store as many elements of one type there, as you have allocated space for. Since C pointer arithmetic interprets *(p + n)
- which is the same as p[n]
and n[p]
- as an access to the address of p
plus n
times the size of an element of the type p
points to, it should now be easier to understand that you can interpret the pointer as the beginning of an array.
For your case, that means you can interpret int **p
as a pointer to an int
-pointer. Past the memory of this pointer, n
more int
pointers may follow, while every one of these pointers represents the address of an int
, past which, once again, n
more ints
may follow. Thus, even though int **p
is actually a pointer to a pointer of type int
, it is possible to interpret it as two-dimensional array. How many elements past your pointer belong to the array is something that you cannot know from neither an array not a pointer, which is why you will usually have a n_size
and/or m_size
argument or something similar.
In the beginning I said that you can "sometimes" treat them as the same. To make this explicit, you can use pointers and arrays interchangeably in these cases:
- When passed to a function a
type[]
"decays" to a type *
e.g. f(type *a)
- If accessing elements with the
[]
operator, a[i]
always resolves to *(a + i)
- When they occur in an expression, e.g.
++a
cf: van der Linden - Deep C