为什么对带下标的数组的赋值有效,而对取消引用的指针算术表达式的赋值却无效?
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.
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
anda
have identical values. Since the name of an array is a synonym for the location of the initial element, the assignmentpa=&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 evaluatinga[i]
, C converts it toa[i]
immediately; the two forms are equivalent. Applying the operator & to both parts of this equivalence, it follows thatand
are also identical:a+i
is the address of thei
-th element beyond a. As the other side of this coin, ifpa
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 butamessage
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.