C++ 修改char*const字符串

C++ 修改char*const字符串,c++,c,string,pointers,runtime-error,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 = "w

我知道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所指向的字符串?

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

C11标准ISO/IEC 9899:2011第6.4.5节描述了字符串文字。

t指向字符串文字修改字符串文字是未定义的行为。C++草稿标准部分2.145字符串文字12段SimSimuli矿:

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

C99标准草案的相关章节为6.4.5字符串文字第6段,该段称Semphasis mine:

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

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

objdump -s -j .rodata
我们可以在下面看到,字符串文本确实可以在只读部分找到。请注意,我必须添加printf,否则编译器将优化字符串文本。“objdump”输出示例:

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


您可以通过将编译器错误重铸为char*,如*char*s+1='a';但是,由于它已经在其他答案中陈述,这是未定义的行为,可能会导致分段错误,因为您正在编辑字符串文字。

如果您想正确测试它,请在函数中初始化字符串,以便初始化可以是动态的,并为此使用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正确释放动态分配。另外,正如其他答案所建议的,始终将字符串文字视为常量字符*

您陈述了标准,但实际上并没有说明程序如何以错误终止。。。只是说。。。Elchonon Edelson给出了实际原因,我认为这是正确的答案。@Alexiswillke该标准是独立于平台的,这些细节是依赖于平台的,这就是为什么该标准使用这种语言作为未定义的行为来涵盖一系列行为,包括工作正常但不可靠的行为。我为典型的现代unix平台添加了更多细节。
char r[] = "world";    
char *const t = r ;
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);
}