don't understand why it no longer requires dereferencing to obtain the array (element)
Well, you are dereferencing, it's just not using the dereference operator *
.
The array subscripting operator []
is serving as job of dereferencing here. quoting C11
, chapter §6.5.2.1
A postfix expression followed by an expression in square brackets []
is a subscripted
designation of an element of an array object. The definition of the subscript operator []
is that E1[E2]
is identical to (*((E1)+(E2)))
. Because of the conversion rules that
apply to the binary +
operator, if E1
is an array object (equivalently, a pointer to the
initial element of an array object) and E2
is an integer, E1[E2]
designates the E2
-th
element of E1
(counting from zero).
It's a syntactic sugar. The expressions x[i]
and *(x+i)
are equivalent. The later satisfies your expectation, whereas, the first one, disguises the dereference operator, but does the exact same job you expected.
That said, also follow the data type closely. What you were expecting, something along the line of *x[i]
would be plain invalid, as it boils down to something like `((x+i) ). Now,
x
is of type int []
(integer array, which decays to a pointer to integer)
x+i
gives you a pointer to int
type result.
- the inner dereference operator is applied to it, resulting an
int
.
- The outer
*
, now will try to operate on an operand of type int
(not a pointer), and, this operation will be a syntactical error, as, the constraint for dereference operator says,
The operand of the unary *
operator shall have pointer type.
in C11
, chapter §6.5.3.2.
Answering the additional question:
Let me use the quote, once again, this one's from paragraph 2, chapter §6.5.2.1
Successive subscript operators designate an element of a multidimensional array object.
If E
is an n
-dimensional array (n ≥ 2)
with dimensions i × j × . . . × k
, then E
(used as
other than an lvalue) is converted to a pointer to an (n − 1)
-dimensional array with
dimensions j × . . . × k
. If the unary *
operator is applied to this pointer explicitly, or
implicitly as a result of subscripting, the result is the referenced (n − 1)
-dimensional
array, which itself is converted into a pointer if used as other than an lvalue. It follows
from this that arrays are stored in row-major order (last subscript varies fastest).
Consider the array object defined by the declaration
int x[3][5];
Here x
is a 3 × 5
array of int
s; more precisely, x
is an array of three element objects, each of which is an
array of five ints. In the expression x[i]
, which is equivalent to (*((x)+(i)))
, x
is first converted to
a pointer to the initial array of five ints. Then i
is adjusted according to the type of x
, which conceptually
entails multiplying i
by the size of the object to which the pointer points, namely an array of five int
objects. The results are added and indirection is applied to yield an array of five ints. When used in the
expression x[i][j]
, that array is in turn converted to a pointer to the first of the ints, so x[i][j]
yields an int
.