文字列リテラルはポインタ!?

"abcd\0"は先頭のaという文字のアドレスを格納するポインタであるようです。
以下に、文字列リテラルとポインタの関係についてねちっこく対比したプログラムを載せます。


/* pointer_study.c */
#include<stdio.h> /* printf */

int main(void)
{
char *ptr;
//ptrに"abcd"のアドレスを代入
ptr ="abcd\0";
//以下の一行はバグになる
//*ptr ="abcd";

//ポインタ"abcd\0"が格納するアドレスを表示
printf("%p\n", "abcd\0");
//ポインタptrが格納するアドレスを表示
printf("%p\n\n", ptr);
//ポインタ"abcd\0"が参照する文字列リテラルを表示
printf("%s\n", "abcd\0");
//ポインタptrが参照する文字列リテラルを表示
printf("%s\n\n", ptr);
/* 以下はコンパイルエラーになる
//ポインタ"abcd\0"が参照する文字列リテラルを一つずつ表示
while(*"abcd" != '\0'){
printf("%c", *"abcd\0");
"abcd\0"++;
}
printf("%s\n", ptr);
*/

//カウンタiを用いればエラーにはならない。
int i=0;
while(*("abcd\0"+i) != '\0'){
printf("%c", *("abcd\0"+i));
i++;
}
printf("%c\n",*("abcd\0"+i));


//ポインタptrが参照する文字列リテラルを一つずつ表示
while(*ptr != '\0'){
printf("%c", *ptr);
ptr++;
}
printf("%c\n\n", *ptr);
//カウンタiを用いて、ポインタ"abcd\0"が格納するアドレスを一つずつ表示する
i=0;
while(*("abcd\0"+i) != '\0'){
printf("%p\n", "abcd\0"+i);
i++;
}
printf("%p\n\n","abcd\0"+i);

//ポインタptrが参照する文字列リテラルを一つずつ表示
ptr ="abcd\0";
while(*ptr != '\0'){
printf("%p\n", ptr);
ptr++;
}
printf("%p\n\n", ptr);

return 0;
}
/* ここまえ */


#コンパイルして実行!!
$ ./pointer_study
0x8048680
0x8048680

abcd
abcd

abcd
abcd

0x8048680
0x8048681
0x8048682
0x8048683
0x8048684

0x8048680
0x8048681
0x8048682
0x8048683
0x8048684