Let's talk about the 3 cases individually:
int *i;
*i=1;
The first line allocates memory for a pointer, but does not initialize it, leaving i with a random garbage value. The second line tries to write to the memory address spelled out by the random garbage, causing undefined behaviour at runtime.
int *i=1;
This allocates memory for a pointer and assigns it the value 1 (i.e. the memory address 0x1
). Since this implicitly casts the integer value 1 to a pointer, you get a warning, since it's extremely rare to ever initialize a pointer to a non-null memory address.
As an aside, if you were to do:
int *i=1;
*i=1;
it would try to write the value 1 to the memory address 0x1
, causing the same undefined behaviour as in your first case.
char *s="acd";
This creates a null-terminated string on the stack and makes s point to it. String literals are the natural thing to assign to a char *, so no warning.