是否可以在C中修改字符串?

Joh*_*ker 65 c string debugging

我用各种各样的C教程和与指针相关的书籍一直在苦苦挣扎几个小时,但我真正想知道的是,如果可以在创建一个char指针后更改它.

这是我尝试过的:

char *a = "This is a string";
char *b = "new string";

a[2] = b[1]; // Causes a segment fault

*b[2] = b[1]; // This almost seems like it would work but the compiler throws an error.
Run Code Online (Sandbox Code Playgroud)

那么有没有办法改变字符串内的值而不是指针地址?

谢谢

编辑:

谢谢大家的回答.现在更有意义了.特别有意义的是,为什么有时它工作正常而其他时候不工作.因为有时候我会传递一个char指针,有时会传递一个char数组(char数组工作正常).

Car*_*ers 141

当您在源代码中编写"字符串"时,它会直接写入可执行文件,因为该值需要在编译时知道(有一些工具可以将软件分开并找到其中的所有纯文本字符串).在您编写时char *a = "This is a string","This is a string"的位置在可执行文件中,而a指向的位置在可执行文件中.可执行映像中的数据是只读的.

您需要做的事情(正如其他答案所指出的那样)是在堆上或堆栈框架中创建不是只读位置的内存.如果声明一个本地数组,则在该堆栈上为该数组的每个元素创建空间,并将字符串文字(存储在可执行文件中)复制到堆栈中的该空间.

char a[] = "This is a string";
Run Code Online (Sandbox Code Playgroud)

您也可以通过在堆上分配一些内存,然后使用a将字符串文字复制到该空间来手动复制该数据.

char *a = malloc(256);
strcpy(a, "This is a string");
Run Code Online (Sandbox Code Playgroud)

每当你使用时分配空间,strcpy()记住malloc()在你完成它时调用(读:内存泄漏).

基本上,您必须跟踪数据的位置.每当你在你的源写一个字符串,该字符串是只读的(否则你将可能改变可执行文件的行为-想象一下,如果你写了free(),再变char *a = "hello";a[0].然后别的地方写了'c'.如果你被允许改变第一性格printf("hello");,你的编译器只存储一次(应该),然后"hello"将输出printf("hello");!)

  • 最后一节解释了我为什么需要只读的原因.谢谢. (11认同)

Jon*_*son 23

不,你不能修改它,因为字符串可以存储在只读存储器中.如果要修改它,可以使用数组,例如

char a[] = "This is a string";
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用malloc分配内存,例如

char *a = malloc(100);
strcpy(a, "This is a string");
free(a); // deallocate memory once you've done
Run Code Online (Sandbox Code Playgroud)

  • 为了完成代码,如果你也可以添加free()调用将会很好. (4认同)

Jef*_*ber 11

很多人对char*和char []与C中的字符串文字的区别感到困惑.当你写:

char *foo = "hello world";
Run Code Online (Sandbox Code Playgroud)

...实际上,你将foo指向一个恒定的内存块(实际上,编译器在这个实例中用"hello world"做的是依赖于实现的.)

使用char []会告诉编译器您要创建一个数组并用内容"hello world"填充它.foo是指向char数组的第一个索引的指针.它们都是char指针,但只有char []指向本地分配和可变的内存块.


Nav*_*een 6

a&b的内存不是由您分配的.编译器可以自由选择只读存储器位置来存储字符.因此,如果您尝试更改它可能会导致seg错误.所以我建议你自己创建一个角色阵列.就像是:char a[10]; strcpy(a, "Hello");


Swe*_*ney 6

您的问题似乎已得到解答,但现在您可能想知道为什么 char *a = "String" 存储在只读内存中。好吧,实际上 c99 标准没有定义它,但大多数编译器选择这种方式,例如:

printf("Hello, World\n");
Run Code Online (Sandbox Code Playgroud)

c99 标准 (pdf) [第 130 页,第 6.7.8 节]:

声明:

char s[] = "abc", t[3] = "abc";
Run Code Online (Sandbox Code Playgroud)

定义“普通”字符数组对象 s 和 t ,其元素用字符串文字初始化。此声明与 char 相同

s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' };
Run Code Online (Sandbox Code Playgroud)

数组的内容是可修改的。另一方面,声明

char *p = "abc";
Run Code Online (Sandbox Code Playgroud)

定义 p 类型为“指向 char 的指针”,并将其初始化为指向一个类型为“char 数组”的对象,长度为 4,其元素用字符串文字初始化。如果尝试使用 p 修改数组的内容,则行为未定义。


Max*_*amy 6

您还可以使用strdup

   The strdup() function returns a pointer to a new string which is a duplicate of the string  s.
   Memory for the new string is obtained with malloc(3), and can be freed with free(3).
Run Code Online (Sandbox Code Playgroud)

以你为例:

char *a = strdup("stack overflow");
Run Code Online (Sandbox Code Playgroud)