【问题标题】:Initializing a string in C [duplicate]在C中初始化一个字符串[重复]
【发布时间】:2012-09-27 12:49:39
【问题描述】:

可能重复:
Difference between char *str=“STRING” and char str[] = “STRING”?

我写了以下代码:

int main()
{
    char *str = "hello";
    str[0] = 'H';
    printf("%s\n", str);
}

这给了我一个分段错误,我不明白为什么。

strpointer to char 不是 const char。即使是这种情况,它也不应该给出如下程序的编译错误:

int main()
{
    const char *str = "hello";
    str[0] = 'H';
    printf("%s\n", str);    
}

它给出一个错误:assignment of read-only location *str

编辑

如果我的代码将指针指向只读位置,我不应该得到编译错误吗?

【问题讨论】:

  • 请使用搜索功能。如果您进行搜索,您会发现数百个完全相同的问题。
  • @Marlon 请在 stackoverflow 上粘贴重复问题的链接
  • 指针不是只读的。它只是指向您的字符串在内存中的存储位置。声明字符串的方式之间存在细微差别,这会改变它的存储方式。
  • “如果我的代码将指针指向只读位置,我不应该得到编译错误。”你所做的是一个完全有效的任务。编译器不知道的是,在标准系统中,常量字符串被放置在只读内存中。在嵌入式系统上,这可能会有所不同。

标签: c arrays string


【解决方案1】:

您分配一个指向常量字符串的指针(它作为文本的一部分出现,因此不是可写内存)。

使用char str[] = "hello"; 进行修复,这将在您的堆栈上创建一个常量字符串的读/写副本。

你所做的是一个完全有效的指针赋值。编译器不知道的是,在标准系统中,常量字符串被放置在只读内存中。在嵌入式(或其他奇怪的)系统上,这可能会有所不同。

根据您的系统,您可以使用 mprotect 并将指针目标上的 VM 标志更改为可写。所以编译器允许这段代码,但你的操作系统不允许。

【讨论】:

  • 字符串文字不是const,也不是常量。它是char 的标准数组,刚好足以容纳所有字符以及在未定义行为的惩罚下不可写入的终止符。
【解决方案2】:

当您使用文字字符串初始化 char * 时,您不应尝试修改其内容:该变量指向不属于您的内存。

可以使用:

char str[] = "hello";
str[0] = 'H';

使用此代码,您已经声明了一个数组,该数组使用文字字符串内容的副本进行初始化,现在您可以修改该数组。

【讨论】:

    【解决方案3】:

    您的代码在运行时有未定义的行为。您正在尝试写入不允许的文字字符串。此类写入可能会触发错误或具有未定义的行为。您的特定 C 编译器有 str 指向只读内存,尝试写入该内存会导致分段错误。虽然不是const,但还是不允许写。

    【讨论】:

      【解决方案4】:
      char *str = "hello";
      

      当你像上面那样声明str时,不能保证它将被存储在内存的哪一部分。 str 可能是只读的,具体取决于实现。所以试图改变它会导致分段错误。

      为了避免分段错误,请将str 声明为字符数组。

      【讨论】:

        【解决方案5】:
        char *str = "hello";
        

        这里的字符串 hello 是一个文字。 字符串文字总是存储在只读存储器中。 这就是您在尝试更改只读内存中的值时遇到分段错误的原因。

        【讨论】:

        • 字符串文字存储在实现希望它们存储的任何地方,不一定是只读的。
        • 在绝大多数情况下,它们存储在只读内存中。
        【解决方案6】:

        将 str 声明为 char* 会为指针保留内存,但不会为字符串保留内存。 编译器可以将“hello”的内存放在他喜欢的任何地方。 您不能保证 str[i] 是可写的,所以这就是为什么在某些编译器中这会导致段错误。

        如果要确保字符串在可写内存中,则必须使用 alloc() 分配内存,也可以使用

        char str[] = "hello";
        

        【讨论】:

        • 对不起,我不明白为什么编译器不能把“你好”的内存放在他喜欢的地方
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-31
        • 2021-03-28
        • 1970-01-01
        • 2015-07-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多