In most contexts, an expression of array type will be implicitly converted from an "N-element array of T" to "pointer to T" and its value will be set to point to the first element of the array. The exceptions to this rule are when the array is an operand of the &
or sizeof
operators, or if the array is a string literal being used to initialize another array in a declaration.
So how does all that relate to your code?
In the line
scanf("%d", &a);
You are applying the &
operator to the array. This suppresses the implicit conversion from "array of T" to "pointer to T" and returns a value of type "pointer to array of T", or T (*)[N]
(hence your first warning). Now it turns out that the value of a pointer to an array and the value of a pointer to the first element of the array are the same, they just have different types. So assuming that a
is at address 0x0001000:
expression type value note
---------- ---- ----- ----
a int * 0x0001000 implicitly converted to pointer
&a int (*)[N] 0x0001000
&a[0] int * 0x0001000
That's why your first call to scanf()
"works"; you're passing the right pointer value, but the compiler is complaining because the type of the expression doesn't match what the function expects. Had you written
scanf("%d", a);
you would not have received any warnings, since the type of a
will be taken to be int *
, which is what scanf()
expects. Note that this is identical to calling
scanf("%d", &a[0]);
As for b
...
You explicitly declare b
as a pointer to int and assign a block of memory to it. When you apply the &
operator to it, what you get back is the address of the variable b
with type int **
(hence the second warning), not the address that b
points to.
expression type value note
---------- ---- ----- ----
b int * 0x0040000 value contained in b
&b int ** 0x0001000 address of b
For that case, you just pass the undecorated b
:
scanf("%d", b);