为什么赋值给一个下标数组工作并赋值给一个解引用的指针算术表达式 - 不是吗?

时间:2015-08-19 15:23:37

标签: c arrays pointers pointer-arithmetic

Kernighan&里奇第二版。表示:

  

索引和指针算术之间的对应关系非常接近。根据定义,类型数组的变量或表达式的值是数组的元素零的地址。因此在任命后   pa = &a[0];

     

paa具有相同的值。由于数组的名称是初始元素位置的同义词,因此赋值pa=&a[0]也可以写为
  pa = a;

     

更令人惊讶的是,至少在第一眼看来,对a[i]的引用也可以写为*(a+i).在评估a[i]时,C将其转换为{{1}立即;这两种形式是等价的。应用运算符&对于这个等价的两个部分,a[i]也是相同的:and是除{a}之外的a+i个元素的地址。作为这个硬币的另一面,如果i是一个指针,表达式可以将它与下标一起使用; papa[i]相同。简而言之,一个数组和索引表达式相当于一个写为指针和偏移的表达式。

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

*(pa+i)

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

为什么呢?非常感谢参考权威来源。

4 个答案:

答案 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。