char *p = "string"; //creates pointer to constant string
char p[] = "string"; //just an array with "string"
我只是有点困惑为什么在第一个例子中创建一个指向常量字符串的指针?它不应该只是一个指针,用“string”引用内存中的一个地方吗?
答案 0 :(得分:22)
在第一种情况下,"string"
可能存储在进程的只读区域中,因此尝试修改p
指向的内存会导致未定义的行为。
在第二种情况下,实际内存在运行时分配并初始化在堆栈上(如果它不是本地变量,则在程序启动过程的相应部分),因此修改内存是正常的。
第一种情况可以这样说明:
+---+ +---+---+---+---+---+---+---+
| | ----> | s | t | r | i | n | g | \0|
+---+ +---+---+---+---+---+---+---+
p
而第二种情况是:
+---+---+---+---+---+---+---+
| s | t | r | i | n | g | \0|
+---+---+---+---+---+---+---+
p
这两个声明有很大的不同,尽管您可能听说过低质量的C编程书籍它们是相同的。
第一个是类型char *
的指针,而第二个是char []
类型的数组。数组标识符在某些上下文中衰减指针,但这不会使它们成为指针。
指针只是一个地址,数组是“整个” - 在第一种情况下sizeof(p)
产生指针的大小(通常为4
或8
,具体取决于目标机器),在第二种情况下,它产生7 * sizeof(char)
,即实际字符串的长度。
答案 1 :(得分:15)
不幸的是,在C语言中是合法的(在C ++ 03中,为了兼容性)。但是任何通过指针修改字符串文字的尝试都会导致未定义的行为。因此,最好始终将字符串文字分配给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
答案 2 :(得分:3)
第一个创建一个指针并将其设置为常量字符串的地址(可能是在页面上没有写保护的区域)。写入此指针是非法的(并且可能会崩溃)。
第二个创建一个数组并将字符复制到其中。写入此数组将写入堆栈中的某个位置,并且完全合法。
答案 3 :(得分:1)
在第一种情况下,“string”可能存储在进程的只读区域中,因此尝试修改p指向的内存会导致未定义的行为。
可以通过重复运行上面的代码来证明。
char *p="string";
你会注意到p的内容(即“字符串”的地址)保持不变。
char p[] = "string";
因此,每次运行p更改的内容时,都会分配这些内存。