You have come across a curiosity of C's declaration syntax.
When you write
int *p = &i;
you are declaring a variable p of type int *, and you are initializing it to point to i.
But the initialization is not equivalent to the standalone assignment
*p = &i; /* WRONG */
Rather, it is equivalent to
p = &i; /* right */
What's actually happening is that there are two slightly different uses of the * character here. When you say
int *p = &i;
the * means that p is being declared as a pointer. (But since this very much determines p's type, some programmers prefer to write it as int* p instead.)
Later, in an actual expression statement, when you use * with a pointer, it means "access the contents of that pointer". If we say
printf("%d\n", *p);
we will fetch the value that p points to (which will actually be i's value). If we say
*p = 5;
we will set the value pointed to by p to 5 (which will actually set i to 5).
Bottom line: When you split up a pointer initialization like
int *p = &i;
into a declaration and separate assignment
int *p;
p = &i;
then yes, it looks like there's something fishy going on. It looks like a * has gotten lost, or something, but actually, when you stop and think about it, it's perfectly correct as-is.
*p = &ias a seperate assignment would be something very differentint i = 5;vs.int i; i = 5;Note that the first form, which uses an initializer, can be used outside of a function, while the latter cannot.