'a' == 'a'
"a" == 'a','\0'

というように文字と文字列は違う。

char a='a';
char b="a";   //エラー。文字列は char に収まりきれない。
char *c = "a"; //"a"という文字列のアドレスを入れているのでOK。
char d[2]="a"; //上記に示したとおり、char2個分だから収まる。

c はポインタ。変数や配列のアドレスを c という名前で管理する。
d は配列。変数の連なりに d という名前を付けている。
その領域を"a"で初期化している。

"a"は変数名のない配列。
しかもプログラムのどこにあるのやら人間には判別つかない。
それではプログラマが利用できないので
名前をつけて"a"のある場所を知る必要がある。
その方法が char *c = "a";

printf("a")では"a"という文字列を表示したいだけで、
"a"のある場所を人間が知る必要ないから
そのままPCにおまかせしている。