更改c字符串中的一个字符

时间:2011-09-25 18:58:44

标签: c arrays

我试图理解为什么以下代码是非法的:

int main ()
{
    char *c = "hello";
    c[3] = 'g'; // segmentation fault here
    return 0;
}

遇到char *c = "hello";时编译器在做什么?

我理解它的方式,它是一个自动的char数组,而c是指向第一个char的指针。如果是这样,c[3]就像*(c + 3),我应该可以进行分配。

只是想了解编译器的工作方式。

3 个答案:

答案 0 :(得分:9)

字符串常量是不可变的。您无法更改它们,即使您将它们分配给char *(因此请将它们分配到const char *,这样您就不会忘记)。

要详细了解一下,您的代码大致相当于:

int main() {
  static const char ___internal_string[] = "hello";
  char *c = (char *)___internal_string;
  c[3] = 'g';
  return 0;
}

这个___internal_string通常被分配给只读数据段 - 任何改变数据的尝试都会导致崩溃(严格来说,其他结果也可能发生 - 这是'未定义行为的一个例子' “)。但是,由于历史原因,编译器允许您分配给char *,给您错误的印象,您可以修改它。

请注意,如果您这样做,它将起作用:

char c[] = "hello";
c[3] = 'g'; // ok

这是因为我们正在初始化一个非const字符数组。虽然语法看起来很相似,但编译器会对它进行不同的处理。

答案 1 :(得分:7)

这些之间存在差异:

char c[] = "hello";

char *c = "hello";

在第一种情况下,编译器在堆栈上为6个字节分配空间(即5个字节用于“hello”,1个用于空终止符。

在第二种情况下,编译器在全局区域(也称为字符串文字)中生成一个名为“hello”的静态const字符串,并在堆栈上分配一个指针,该指针被初始化为指向该const字符串。

您无法修改常量字符串,这就是您遇到段错误的原因。

答案 2 :(得分:1)

您无法更改字符串文字的内容。你需要复制一份。

#include <string.h>

int main ()
{
    char *c = strdup("hello");  // Make a copy of "hello"
    c[3] = 'g';
    free(c);
    return 0;
}