Reputation: 1948
As far as I know, the derefence operator *
returns the value stored in the pointer address. What I'm confused by is the behavior when the operator is used with pointer of an array. For example,
int a[4][2];
Then a
is internally converted to pointer of first element of array of 4 elements of 2 ints. Then which value does *a
return? I'm really confused!
Upvotes: 9
Views: 505
Reputation: 263257
This:
int a[4][2];
defined a
an array of 4 elements, each of which is an array of 2 int
elements. (A 2-dimensional array is nothing more or less than an array of arrays.)
An array expression is, in most contexts, implicitly converted to a pointer to the array object's initial (zeroth) element. (Note the assumption that there is an array object; that has caused some angst, but it's not relevant here.)
The cases where an array expression is not converted to a pointer are:
sizeof
;&
; and(Compiler-specific extensions like gcc's typeof
might create more exceptions.)
So in the expression *a
, the subexpression a
(which is of type int[4][2]
) is implicitly converted to a pointer of type int(*)[2]
(pointer to array of 2 int
s). Applying unary *
dereferences that pointer, giving us an expression of type int[2]
.
But we're not quite done yet. *a
is also an expression of array type, which means that, depending on how it's used, it will probably be converted again to a pointer, this time of type int*
.
If we write sizeof *a
, the subexpression a
is converted from int[4][2]
to int(*)[2]
, but the subexpression *a
is not converted from int[2]
to int*
, so the expression yields the size of the type int[2]
.
If we write **a
, the conversion does occur. *a
is of type int[2]
, which is converted to int*
; dereferencing that yields an expression of type int
.
Note that despite the fact that we can legally refer to **a
, using two pointer dereference operations, there are no pointer objects. a
is an array object, consisting entirely of 8 int
objects. The implicit conversions yield pointer values.
The implicit array-to-pointer conversion rules are in N1570 section 6.3.2.1 paragraph 3. (That paragraph incorrectly gives _Alignof
as a fourth exception, but _Alignof
cannot be applied to an expression. The published C11 standard corrected the error.)
Recommended reading: Section 6 of the comp.lang.c FAQ.
Upvotes: 6
Reputation: 223872
The type of a
is int[4][2]
, so the type of *a
(or equivalently a[0]
) is int[2]
.
It is not the same as a[0][0]
. If you do this:
int a[4][2];
printf("%d\n",*a);
The compiler will tell you this:
warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘int *’
Since an array (in this case one of type int [2]
) is being passed to a function, it decays to a pointer to the first element in this context.
If on the other hand you had **a
, that is equivalent to a[0][0]
and has type int
.
Upvotes: 9