修改一个char * conststring

我知道const char *是一个指向const char *的指针,而char *const是一个指向char的常量指针。 我正在testing下面的代码:

 const char *s = "hello"; // Not permitted to modify the string "hello" char *const t = "world"; // Not permitted to modify the pointer t s = "hello2"; // Valid // t = "world2"; // Invalid, gives compilation error // *(s + 1) = 'a'; // Invalid, gives compilation error *(t + 1) = 'a'; // Why does this not work? 

最后一行不会给出任何错误,但会导致程序意外终止。 为什么修改指向的string不允许?

t指向一个string文字,它是未定义的行为来修改一个string文字 。 C ++草案标准部分2.14.5 string文字12段说( 强调我的 ):

是否所有string文字都是不同的(即,是否存储在不重叠的对象中)是实现定义的。 尝试修改string文字的效果是未定义的

C99草案标准中的相关部分是6.4.5 string文字 (说明我的 )的第6段:

没有说明这些数组是否是不同的,只要它们的元素具有适当的值。 如果程序试图修改这样一个数组,行为是不确定的。

在一个典型的现代Unix平台上,你会发现在只读段中的string文字 ,如果我们试图修改它,会导致访问冲突。 我们可以使用objdump来检查只读部分,如下所示:

 objdump -s -j .rodata 

我们可以在下面的活动例子中看到,string文字确实会在只读部分find。 请注意,我不得不添加一个printf否则编译器会优化string文字。 样例` objdump输出:

 Contents of section .rodata: 400668 01000200 776f726c 64002573 0a00 ....world.%s.. 

另一种方法是将一个string的副本指向一个数组,如下所示:

 char r[] = "world"; char *const t = r ; 

尽pipeC语言中的string正式具有char[]char数组,而不是const )types,但C标准明确指出它们必须被视为不可修改。 编译器倾向于将string文字放在只读段中,因此尝试修改它们会导致访问冲突。

string文字在C11标准(ISO / IEC 9899:2011)的6.4.5节中描述。

您可以通过将其重新编译为char*来绕过编译器错误,如*((char*)s + 1) = 'a'; 但由于已经在其他答案中已经确定,这是未定义的行为,并且可能会导致分段错误,因为您正在编辑string文字。

如果你想正确地testing它,初始化函数中的string,这样初始化可以是dynamic的,并使用strdup()

 int main(int argc, char **argv) { char *d1 = strdup("hello"); char *d2 = strdup("world"); const char *s = d1; char *const t = d2; ... free(d1); free(d2); } 

主要使用d1和d2variables,以便在最后使用free()可以正确地释放dynamic分配。 另外,正如其他答案所示,总是将string字面值视为const char *