Литеральная строка типа "good"
действительно хранится как (только для чтения) массив символов. Кроме того, все строки в C должны быть завершены специальным нулевым символом '\0'
.
Когда вы делаете поставку
string = "good";
что действительно происходит, так это то, что вы string
указываете на первый символ в этом массиве.
Функции, обрабатывающие строки, знают, как обращаться с такими указателями, и знают, как перебирать такие массивы, используя указатель, чтобы найти все символы в строке, пока он не найдет терминатор.
Если посмотреть немного по-другому, компилятор создает свой массив
char internal_array[] = { 'g', 'o', 'o', 'd', '\0' };
затем вы делаете string
указатель на первый элемент в массиве
string = &internal_array[0];
Обратите внимание, что &internal_array[0]
фактически равно internal_array
, поскольку массивы естественным образом распадаются на указатели на их первый элемент.