在C++中创建一个可修改的字符串文字

Ann*_*nne 5 c++ string

是否可以在C++中创建可修改的字符串文字?例如:

char* foo[] = {
    "foo",
    "foo"
};
char* afoo = foo[0];
afoo[2] = 'g'; // access violation
Run Code Online (Sandbox Code Playgroud)

这会产生访问冲突,因为"foo"被分配在只读存储器中(我相信.rdata部分).有没有办法强迫"foo"进入可写内存(.data部分)?即使通过一个pragma也是可以接受的!(Visual Studio编译器)

我知道我可以做strdup和其他一些事情来解决这个问题,但是我想特别知道我能不能按照我的要求去做.:)

Cog*_*eel 9

由于这是C++,"最佳"答案是使用一个字符串类(std::string,QString,CString根据您的环境,等等).

要直接回答您的问题,您不应该修改字符串文字.标准说这是未定义的行为.你真的需要以这种或那种方式复制字符串,否则你写的是不正确的C++.

  • 对于`std :: string`为+1,对于奇怪的非标准字符串为-1. (2认同)
  • 详细说明,如果你使用的是一个拥有自己的字符串类的框架,那么你只需要通过尝试将`std :: string`放入混合中来使你的生活变得更加困难.因此"取决于你的环境" (2认同)

Mic*_*urr 5

我认为您可以使用的最接近的方法是char[]使用文字初始化普通格式(而不是char * []):

char foo[] = "foo";
Run Code Online (Sandbox Code Playgroud)

不过,仍然会在某些时候执行复制。

唯一的解决方法是使用系统级调用将字符串文字所在的页面标记为可写。那时,您并不是真正在谈论C或C ++,而是在谈论Windows(或您正在运行的任何系统)。在大多数系统上,这可能是可能的(除非数据确实在ROM中,例如在嵌入式系统上可能是这种情况),但我当然不知道细节。

哦,别忘了在您的示例中:

char* foo[] = {
    "foo",
    "foo"
};
Run Code Online (Sandbox Code Playgroud)

由于标准(C99 6.4.5 / 6“字符串文字”)说:

如果它们的元素具有适当的值,则不确定这些数组是否不同。

关于该数组中的2个指针是否指向相同或分离的对象,尚不确定。几乎所有的编译器都将那些指针指向同一地址的同一对象,但并非必须如此,而指向字符串文字的更复杂的情况可能会使编译器产生2个单独的相同字符串。

您甚至可能遇到一个字符串文字存在于另一个字符串内部的情况:

char* p1 = "some string";
char* p2 = "string";
Run Code Online (Sandbox Code Playgroud)

p2可能指向指向的字符串的尾端p1

因此,如果您开始通过某种技巧在系统上执行更改字符串文字的操作,则可能最终无意间修改了“其他”字符串。这是未定义行为可以带来的事情之一。


Fer*_*yer 1

您可以创建一个多维字符数组:

#include <iostream>

int main(int argc, char** argv)
{
    char foo[][4] = {
        "foo",
        "bar"
    };
    char* afoo = foo[0];
    afoo[2] = 'g';
    std::cout << afoo << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

定义数组的更详细方法:

char foo[][4] = {
    {'f', 'o', 'o', '\0'},
    {'b', 'a', 'r', '\0'}
};
Run Code Online (Sandbox Code Playgroud)

  • 您仍然可以使用字符串文字,不必将所有字符指定为字符文字。 (2认同)
  • 另外,安妮应该记住,如果她这样做,则 4 必须是最长字符串的大小 +1。使用字符串类确实是更好的选择,但这与她想要的最接近。 (2认同)