C言語の文字列リテラルにおける配列とポインタの違い

C言語を勉強し始めた時に、以下の2パターンの違いに躓きました。

(1) char str[] = "abc";
(2) char *str = "abc";

(1)が配列の初期化で、(2)がポインタの初期化です。

この2つの定義は似ていますが、実際は違います。
今回はこの違いについて書いていきます。

ー(1)についてー

char str[] = {'a', 'b', 'c', '¥0'};

と同義です。charの配列初期化を省略して書いている形になります。

ANSI C以前のC言語では

static char str[] = {'a', 'b', 'c', '¥0'};

または

static char str[] = "abc";

と書かなければいけなかったようです。

こちらは文字の配列のため書き換えが可能です。

char str[] = "abc";
str[0] = "d";  /* 可能 */

"abc"の"a"が存在するアドレスで書き換えられます。
書き換えをしないようにするにはconst修飾子で配列を指定する必要があります。

ー(2)についてー

この場合における"abc"は、「charの配列」であり、
式の中なので「charへのポインタ」に読み替えられてstrに代入しています。
strは"abc"のアドレスを格納する入れ物みたいなものです。

こちらは書き換えが不可です。
文字列リテラルは、通常は書き換え禁止領域に確保されるので
書き換えようとすると書き込み禁止のエラーが起きます。

char *str = "abc";
str[0] = "d";  /* エラー */

以上になります。

参考: