Kernighan&里奇第二版。表示:
索引和指针算术之间的对应关系非常接近。根据定义,类型数组的变量或表达式的值是数组的元素零的地址。因此在任命后
pa = &a[0];
pa
和a
具有相同的值。由于数组的名称是初始元素位置的同义词,因此赋值pa=&a[0]
也可以写为
pa = a;
更令人惊讶的是,至少在第一眼看来,对
a[i]
的引用也可以写为*(a+i).
在评估a[i]
时,C将其转换为{{1}立即;这两种形式是等价的。应用运算符&对于这个等价的两个部分,a[i]
也是相同的:and
是除{a}之外的a+i
个元素的地址。作为这个硬币的另一面,如果i
是一个指针,表达式可以将它与下标一起使用;pa
与pa[i]
相同。简而言之,一个数组和索引表达式相当于一个写为指针和偏移的表达式。
阅读本文后,我希望这两个程序的工作方式相同:
*(pa+i)
但只有第一个实际上有效。对于第二个,我得到了分段错误。
为什么呢?非常感谢参考权威来源。
答案 0 :(得分:3)
定义和初始化数组时,所有数组都分配在可修改的内存中(通常是堆栈),因此您可以按照自己的方式修改数组。
当您使用字符串文字时,编译器将为您提供指向只读零终止数组char
的指针。尝试修改此数组(在第二个示例中执行此操作)会导致未定义的行为。
答案 1 :(得分:2)
它与指针算法无关。这是因为在第二个程序中:
char *arr = "hello";
arr
指向一个字符串文字,不能修改。
答案 2 :(得分:1)
这是因为第一个代码段中的arr
是一个char
数组,可以修改,而在第二个代码段中,它是一个字符串文字,不会发生变化。
字符串文字可能存储在内存的只读部分中,修改它会调用未定义的行为。
答案 3 :(得分:0)
K& R( 5.5字符指针和函数):
这些定义之间存在重要差异:
char amessage[] = "now is the time"; /* an array */ char *pmessage = "now is the time"; /* a pointer */
amessage
是一个数组,大到足以容纳序列 字符和′\0′
初始化它。个性人物 可以更改数组中的内容,但amessage
将始终引用 相同的存储空间另一方面,pmessage
是指针, 初始化为指向字符串常量;指针可以 随后被修改为指向别处,但结果是 如果您尝试修改字符串内容,则为undefined。