int *aptr = 21;
does not store 21
in *aptr
. When =
is used in a declaration, it sets the initial value for the thing being declared (which is aptr
), not for the “expression picture” used for the declaration (*aptr
).
In C declarations, we use pictures of a sort to describe the type. Generally, in a declaration like int declarator
, declarator
gives a picture of some expression we will use as an int
. For example, int *foo
says *foo
will be an int
, so it declares foo
to be a pointer to an int
. Another example is that int foo[3]
says foo[i]
will be an int
, so it declares foo
to be an array of int
. Note that these are declaring foo
, not *foo
or foo[i]
, so, when an initial value is given, it is for initializing foo
, not *foo
or foo[i]
.
21
is not a proper value for a pointer, so the compiler complains. (Integers can be converted to pointers by using casts, but this is a special use case that requires ensuring the integers represent addresses made available in the C implementation.)