jwqwerty jwqwerty - 2 months ago 5x
C Question

Confusion about dereference operator ("*") in C

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];

is internally converted to pointer of first element of array of 4 elements of 2 ints. Then which value does
return? I'm really confused!



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:

  • When it's the operand of sizeof;
  • When it's the operand of unary &; and
  • When it's a string literal in an initializer used to initialize an array object.

So in the expression *a, the subexpression a (which is of type int[2][2]) is implicitly converted to a pointer of type int(*)[2] (pointer to array of 2 ints). 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 conversion doesn't occur, 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 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.