为什么对带下标的数组的赋值有效,而对取消引用的指针算术表达式的赋值却无效?

Why assignment to a subscripted array works and assignment to a dereferenced pointer arithmetic expression - doesn't?

Kernighan & Ritchie 第 2 版。说:

The correspondence between indexing and pointer arithmetic is very close. By definition, the value of a variable or expression of type array is the address of element zero of the array. Thus after the assignment
pa = &a[0];

pa and a have identical values. Since the name of an array is a synonym for the location of the initial element, the assignment pa=&a[0] can also be written as
pa = a;

Rather more surprising, at least at first sight, is the fact that a reference to a[i] can also be written as *(a+i). In evaluating a[i], C converts it to a[i] immediately; the two forms are equivalent. Applying the operator & to both parts of this equivalence, it follows that and are also identical: a+i is the address of the i-th element beyond a. As the other side of this coin, if pa is a pointer, expressions may use it with a subscript; pa[i] is identical to *(pa+i). In short, an array-and-index expression is equivalent to one written as a pointer and offset.

阅读本文后,我希望这两个程序的工作方式相同:

/* Program 1 */
#include <stdio.h>


int main()
{
    char arr[] = "hello";
    arr[0] = 'H';
    printf("%s\n", arr);

}

/* Program 2 */
#include <stdio.h>


int main()
{
    char *arr = "hello";
    arr[0] = 'H';
    printf("%s\n", arr);

}

但实际上只有第一个有效。对于第二个,我遇到了分段错误。

为什么?参考权威来源将不胜感激。

那是因为第一个代码段中的 arr 是一个 char 数组并且可以修改,而在第二个代码段中它是一个字符串文字,不会发生变化。

字符串文字可能存储在内存的只读部分,修改它会调用未定义的行为。

与指针运算无关。因为在第二个程序中:

char *arr = "hello";

arr 指向一个字符串文字,不能修改。

当您定义和初始化数组时,所有数组都分配在可修改的内存(通常是堆栈)中,因此您可以随意修改数组。

当您使用字符串文字时,编译器将为您提供一个指向char只读 零终止数组的指针。尝试修改此数组(您在第二个示例中所做的)会导致 未定义的行为

K&R(5.5 字符指针和函数):

There is an important difference between these definitions:

char amessage[] = "now is the time";   /* an array */
char *pmessage = "now is the time";    /* a pointer */

amessage is an array, just big enough to hold the sequence of characters and ′[=12=]′ that initializes it. Individual characters within the array may be changed but amessage will always refer to the same storage. On the other hand, pmessage is a pointer, initialized to point to a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to modify the string contents.