修改char * const字符串

时间:2013-10-15 03:44:51

标签: c++ c string pointers runtime-error

我知道const char *是指向const char的指针,而char *const是指向char的常量指针。 我在以下代码中测试它:

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?    

最后一行没有给出任何错误,但导致程序意外终止。为什么修改t指向的字符串是不允许的?

4 个答案:

答案 0 :(得分:7)

t指向字符串文字修改字符串文字是未定义的行为。 C ++草案标准部分2.14.5 字符串文字 12 表示(强调我的):

  

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

C99标准草案的相关部分是6.4.5 字符串文字 6 ,其中写着(强调我的):< / p>

  

如果这些数组的元素具有不同的数据,则未指定   适当的价值观如果程序试图修改这样的数组,则行为是   未定义。

在典型的现代Unix平台上,您会在只读段中找到字符串文字,如果我们尝试修改它,将导致访问冲突。我们可以使用 objdump 来检查只读部分,如下所示:

objdump -s -j .rodata

我们可以在下面的live example中看到字符串文字确实可以在只读部分中找到。请注意,我必须添加printf,否则编译器会优化字符串文字。示例` objdump 输出:

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

另一种方法是让t指向一个带有字符串文字副本的数组,如下所示:

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

答案 1 :(得分:3)

虽然C中的字符串文字正式具有char[]类型(char的数组,而不是const),但C标准明确规定必须将它们视为不可修改的。编译器倾向于将字符串文字放在只读段中,因此尝试修改它们会导致访问冲突。

字符串文字在C11标准(ISO / IEC 9899:2011)的6.4.5部分中描述。

答案 2 :(得分:1)

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

答案 3 :(得分:1)

如果要正确测试它,请在函数中初始化字符串,以便初始化可以是动态的,并使用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和d2变量,以便最后使用free()正确释放动态分配。此外,正如其他答案所示,始终将字符串文字视为const char *