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

时间:2010-06-16 16:23:27

标签: c++ string

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

char* foo[] = {
    "foo",
    "foo"
};
char* afoo = foo[0];
afoo[2] = 'g'; // access violation

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

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

6 个答案:

答案 0 :(得分:9)

由于这是C ++,“最佳”答案是使用字符串类(std::stringQStringCString等,具体取决于您的环境。)

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

答案 1 :(得分:4)

我认为你最接近的是用文字初始化普通char[](不是char * []):

char foo[] = "foo";

尽管如此,它仍会在某些时候执行复制。

唯一的另一种方法是使用系统级调用将字符串文字所在的页面标记为可写。那时你并不是在谈论C或C ++,你真的在​​谈论Windows(或者你正在运行的任何系统)。它可能在大多数系统上都有可能(除非数据真的在ROM中,例如嵌入式系统可能就是这种情况),但我肯定不知道细节。

哦,不要忘记在你的例子中:

char* foo[] = {
    "foo",
    "foo"
};

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

  

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

无法确定该数组中的2个指针是指向相同还是单独的对象。几乎所有的编译器都会将这些指针指向同一个地址的同一个对象,但它们没有必要,并且一些更复杂的指向字符串文字的情况可能会让编译器提供2个独立的相同字符串。

你甚至可能有一个场景,其中一个字符串文字存在于另一个内部:

char* p1 = "some string";
char* p2 = "string";

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

因此,如果你开始通过一些hack来改变字符串文字,你可以在一个系统上执行,你可能会无意中修改一些“其他”字符串。这是未定义行为带来的事情之一。

答案 2 :(得分:2)

如果将字符串存储在数组中,则可以更改它。

没有办法'正确'写入只读内存。

当然,您可以停止使用C字符串。

答案 3 :(得分:1)

我不会这样做。因此,我只能提供一个你可以尝试的令人讨厌的丑陋黑客: 获取常量文字所在的页面并取消保护该页面。请参阅Win32的VirtualProtect()函数。但是,即使这样可行,也不能始终保证正确的行为。最好不要这样做。

答案 4 :(得分: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;
}

更详细的定义数组的方法:

char foo[][4] = {
    {'f', 'o', 'o', '\0'},
    {'b', 'a', 'r', '\0'}
};

答案 5 :(得分:-3)

   (char[]){"foo"}