c – Initialization from incompatible pointer type warning when assigning to a pointer
c – Initialization from incompatible pointer type warning when assigning to a pointer
&arr
gives an array pointer, a special pointer typeint(*)[5]
which points at the array as whole.arr
, when written in an expression such aint *q = arr;
, decays into a pointer to the first element. Completely equivalent toint *q = &arr[0];
In the first case you try to assign a int(*)[5]
to a int*
. These are incompatible pointer types, hence the compiler diagnostic message.
As it turns out, the array pointer and the int pointer to the first element will very likely have the same representation and the same address internally. This is why the first example works even though it is not correct C.
TL;DR Check the types.
&arr
is of typeint (*) [5]
(pointer to an array of 5int
s).arr
is of typeint [5]
, but not always.
Quoting C11
, chapter §6.3.2.1, (emphasis mine)
Except when it is the operand of the
sizeof
operator, the_Alignof
operator, or the
unary&
operator, or is a string literal used to initialize an array, an expression that has
type ‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’ that points
to the initial element of the array object and is not an lvalue.
hence,
int *q = arr; // int[5] decays to int *, == LHS
and
int *q = &arr[0]; // RHS == LHS
are same, whereas,
int *q = &arr; // LHS (int *) != RHS (int (*) [5])
is a mismatched type expression.
Now, it works, because, as already mentioned in Lundins answer, the address of the array variable is likely to be the same as the address of the first element of the array, so despite the type mismatch, the value is same, so this seems to work.
c – Initialization from incompatible pointer type warning when assigning to a pointer
These are the ways to point to a (beginning of) array (without a warning), both work:
int *q = arr;
/* OR */
int *q = &arr[0];
This one is something in between, and will generate a warning:
int *q = &arr;