将指针用作数组并没有本质上的错误,除非这些指针指向常量数据(并且字符串文字是常量数据)。尽管在语义上不正确,但在过去没有内存保护的情况下,pmessage[0] = 'n';
实际上会产生不可预测的结果(例如,影响程序中相同文字的所有出现)。在现代操作系统上,由于内存保护到位,这不可能发生。字符串文字和其他常量被放在可执行文件的所谓只读部分中,当可执行文件被加载到内存中以创建进程时,包含只读部分的内存页面被设为只读,即任何更改其内容的尝试都会导致分段错误。
char amessage[] = "now is the time";
实际上是以下内容的语法糖:
char amessage[] = { 'n','o','w',' ','i','s',' ','t',
'h','e',' ','t','i','m','e','\0' };
即,它创建一个包含 16 个字符的数组并使用字符串“now is the time”(连同 NULL 终止符)初始化其内容。
另一方面
char *pmessage = "now is the time";
将相同的字符串数据放在只读数据的某处,并将其地址分配给指针pmessage
。它的工作原理类似于:
// This one is in the global scope so the array is not on the stack
const char _some_unique_name[] = "now is the time";
char *pmessage = _some_unique_name;
_some_unique_name
选择它是为了不与程序中的任何其他标识符发生冲突。通常使用 C 语言不允许但对汇编器和链接器来说可以的符号(例如,像 in 之类的点string.1634
)。
您可以更改指针的值 - 这将使其指向其他内容,例如指向另一个字符串。但是您不能更改数组名称后面的地址,即amessage
始终引用最初为其分配的相同数组存储。
You can refer to individual elements of each string using amessage[i]
or pmessage[i]
but you can only assign to the elements of amessage
as they are located in the read-write memory.