【问题标题】:Changing string value using a pointer in C++ [duplicate]使用 C++ 中的指针更改字符串值 [重复]
【发布时间】:2014-02-10 18:44:56
【问题描述】:

运行以下代码时出现分段错误:-

char *p ="Hello";
*p = 'M';

我打算用'M' 替换字符串"Hello" 的第一个字符。但是我遇到了分段错误。可能是什么原因?

【问题讨论】:

  • char *p="Hello" 更改为char p[]="Hello"
  • 否:将 char *p ="Hello"; 更改为 std::string p="Hello";

标签: c++ string pointers


【解决方案1】:

这是未定义的行为。为了与旧的 C 代码兼容,C++ 编译器允许您将非const 指针指向字符串文字(例如您的"Hello"),但您不能通过它们进行便携式编写。

最好使用:

const char* p = "Hello";        // if you really need a pointer, probably so you
                                // can move it within the text, point it at other
                                // text, set it to a NULL sentinel after use...

const char[] hello = "Hello";   // if you're really only interested in the text

【讨论】:

  • 无意冒犯,UB 绝对是准确的表达方式。但是我真的很讨厌看到人们到处说“UB”,而只是说“你不被允许这样做”要简单得多,尤其是对初学者来说。
  • @WiSaGaN:没有冒犯;-)。无论哪种方式都有利弊,但我确实觉得我已经做到了:“但你不能通过它们便携地写”。
  • "便携" 再次破坏了它。 :D
  • @WiSaGaN:它只是......你确实意识到一些仍然常用的编译器实际上支持可写字符串文字 - 例如微软通过命令行开关?从记忆中,我认为甚至可以明确控制是否应该共享任何缓冲区。如果实现决定支持它,未定义的行为并不意味着“你不能这样做”。可怕的想法要依赖它! :-)
  • “便携”与“UB”一样精确。但对我的口味来说太迂腐了,初学者很难掌握。那就是我的意思。 ;-)
【解决方案2】:

C++ 和 C 中的任何字符串文字(例如代码中的 "Hello")都是 const char [6] 类型,并且可以隐式分配给任何 const char * 值:

const char * str="Hello";

表明它驻留在操作系统标记为只读的内存中(您应该已经收到编译器警告)。因此,当您尝试更改该内存位置时将引发异常。

编译器将它放在只读内存中的原因是因为您可能在代码的不同部分使用了另一个相同(甚至相似)的字符串文字"Hello"。通过将字符串文字的内存位置标记为只读,编译器只需将字符串文字在内存中存储一​​次。

还要注意,C++ 标准并不要求编译器将字符串文字放入只读内存,它只是说修改字符串文字是未定义的行为。然而,在实践中,字符串文字存储在任何现代操作系统或编译器的只读内存中。

【讨论】:

  • 类型其实是const char[6]
  • 是的,你是对的。但是,强制转换为 const char * 始终是隐含的。我会编辑我的帖子
  • "you may be using another same string" - 是的,但有趣的是编译器允许共享内存,即使是不同的字符串,例如“Hello Hello”和“Hello”,后者可以在前者的第二个单词中找到(同时仍然共享 NUL 终止符)。
  • 好的,刚刚更新了我的答案。
【解决方案3】:

编译器将“Hello”的字符串放入只读内存段并为您提供指向它的指针。允许您将指针分配给 char* 的事实是为了向后兼容。 C++ 声明这是未定义的行为。

如果您想更改字符串,请像这样声明它:

char p[]="Hello";

【讨论】:

    猜你喜欢
    • 2023-04-01
    • 2018-05-06
    • 2014-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-12
    • 1970-01-01
    相关资源
    最近更新 更多