修改一个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 *
。