指向C中常量字符串的指针

指向C中常量字符串的指针,c,arrays,pointers,constants,C,Arrays,Pointers,Constants,我只是有点困惑,为什么在第一个示例中它会创建一个指向常量字符串的指针?它不应该只是一个指针,用“string”引用内存中的某个位置吗?在第一种情况下,“string”可能存储在进程的只读区域中,因此试图修改p指向的内存将导致未定义的行为 在第二种情况下,实际内存在运行时在堆栈上分配和初始化(或者在程序启动时在进程的适当部分,如果它不是局部变量),因此修改内存是可以的 第一种情况可以这样说明: char *p = "string"; //creates pointer to constant st

我只是有点困惑,为什么在第一个示例中它会创建一个指向常量字符串的指针?它不应该只是一个指针,用“string”引用内存中的某个位置吗?

在第一种情况下,
“string”
可能存储在进程的只读区域中,因此试图修改
p
指向的内存将导致未定义的行为

在第二种情况下,实际内存在运行时在堆栈上分配和初始化(或者在程序启动时在进程的适当部分,如果它不是局部变量),因此修改内存是可以的

第一种情况可以这样说明:

char *p = "string"; //creates pointer to constant string

char p[] = "string"; //just an array with "string"
鉴于第二种情况是:

+---+           +---+---+---+---+---+---+---+
|   |   ---->   | s | t | r | i | n | g | \0|
+---+           +---+---+---+---+---+---+---+
  p
这两个声明有着显著的区别,尽管您可能在低质量的C编程书籍中听说过它们是相同的

第一个是
char*
类型的指针,而第二个是
char[]
类型的数组。数组标识符在某些上下文中衰减为指针,但这并不使它们成为指针

指针只是一个地址,数组是“全部”——在第一种情况下
sizeof(p)
产生指针的大小(通常
4
8
,取决于目标机器),在第二种情况下,它产生
7*sizeof(char)
,实际字符串的长度。

第一个指针创建一个指针,并将其设置为常量字符串的地址(可能位于页面上没有写保护的区域)。写入此指针是非法的(可能会崩溃)


第二个创建一个数组并将字符复制到其中。写入此数组将写入堆栈上的某个位置,这是完全合法的。

不幸的是,它在C中是合法的(为了兼容性,在C++03中也是合法的)。但是,任何通过指针修改字符串文字的尝试都将导致未定义的行为。因此,最好总是将字符串文本分配给
const char*

+---+---+---+---+---+---+---+
| s | t | r | i | n | g | \0|
+---+---+---+---+---+---+---+
              p
在第一种情况下,“string”可能存储在进程的只读区域中,因此试图修改p指向的内存将导致未定义的行为

可以通过反复运行上述代码行来证明这一点

const char * cp = "Hello"; //OK
char* p = "Hello"; //OK in C and C++03 (unfortunately), Illegal in C++11
cp[0] = 'Y'; //Compile-time error, good
p[0] = 'Y'; //no compiler error, undefined behavior
您会注意到p的内容(即“string”的地址)保持不变

char *p="string";

因为这些内存是被分配的,所以每次运行p的内容都会发生变化。

您可能需要阅读的第6节(和其他部分)。发现一些有趣的内容:“可执行文件的只读区域”:也许“进程”在这里更重要。。。“可执行文件”更侧重于包含程序的磁盘文件,但关键是,大多数现代操作系统加载器将把文件内容复制到的内存设为只读。我喜欢你把你的第二个案例
p
放在“I”下面。。。我的一部分人想把它放在“s”下面,强调“数组从…开始”-因为理解数组偏移量很重要-但是你强调了p是所有包含文本数据的数组,这在本文中更为重要+回答得很好。在第一种情况下,对指针的写入在C中不是非法的,它是未定义的行为。它可能会导致内存保护错误,或者工作正常。它完全取决于编译器操作系统和机器体系结构的结合。
char p[] = "string";