Kernighan &里奇第二版说:
索引和指针运算之间的对应关系非常密切。根据定义,数组类型的变量或表达式的值是数组元素0的地址。因此在赋值
之后pa = &a[0];
pa
和a
的值相同。由于数组的名称是初始元素位置的同义词,因此赋值pa=&a[0]
也可以写成pa = a;
更令人惊讶的是,至少乍一看,对
a[i]
的引用也可以写成*(a+i).
在计算a[i]
时,C立即将其转换为a[i]
;这两种形式是等价的。应用运算符&对于这个等价的两个部分,可以得出and
也是相同的:a+i
是i
在a之后的第一个元素的地址。作为硬币的另一面,如果pa
是一个指针,表达式可以带下标使用它;pa[i]
与*(pa+i)
相同。简而言之,一个数组-索引表达式相当于一个写为指针和偏移量的表达式。
看完这篇文章后,我希望这两个程序的工作方式是一样的:
/* Program 1 */
#include <stdio.h>
int main()
{
char arr[] = "hello";
arr[0] = 'H';
printf("%sn", arr);
}
/* Program 2 */
#include <stdio.h>
int main()
{
char *arr = "hello";
arr[0] = 'H';
printf("%sn", arr);
}
但是只有第一个是有效的。第二个我得到分割错误。
为什么?请参考权威资料
当你定义和初始化数组时,所有的数组都是在可修改内存中分配的(通常是堆栈),所以你可以按你想要的方式修改数组。
当你使用字符串字面值时,编译器会给你一个指向只读以零结尾的char
数组的指针。试图修改这个数组(在第二个例子中就是这样做的)会导致未定义的行为。
与指针运算无关。这是因为在第二个程序中:
char *arr = "hello";
arr
指向一个不能修改的字符串字面值
这是因为第一个代码片段中的arr
是char
数组,可以修改,而在第二个代码片段中,它是一个字符串文字,不受更改。
字符串字面值可能存储在内存的只读区,修改它将调用未定义的行为。
K&R (5.5字符指针和函数):
这两个定义之间有一个重要的区别:
char amessage[] = "now is the time"; /* an array */ char *pmessage = "now is the time"; /* a pointer */
amessage
是一个数组,它的大小刚好可以容纳和初始化它的′ ′
。单个字符数组内的值可以被更改,但amessage
将始终引用相同的存储空间。另一方面,pmessage
是指针,初始化为指向字符串常量;指针可以。随后被修改为指向其他地方,但是的结果是