指向C中的const字符串的指针

char *p = "string"; //creates pointer to constant string char p[] = "string"; //just an array with "string" 

我只是有点困惑为什么在第一个例子中创建一个指向常量字符串的指针? 它不应该只是一个指针指向内存中有“字符串”的地方吗?

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

 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 

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

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

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

 +---+ +---+---+---+---+---+---+---+ | | ----> | s | t | r | i | n | g | \0| +---+ +---+---+---+---+---+---+---+ p 

而第二种情况是:

 +---+---+---+---+---+---+---+ | s | t | r | i | n | g | \0| +---+---+---+---+---+---+---+ p 

这两个声明有很大的不同,尽管您可能听说它们与低质量的C编程书籍相同。

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

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

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

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

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

可以通过重复运行上面的代码行来certificate。

 char *p="string"; 

你会注意到p的内容(即“字符串”的地址)保持不变。

 char p[] = "string"; 

因此,每次运行p更改的内容时,都会分配这些内存。