我已经花了几个小时阅读各种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.
那么有没有办法改变字符串内部的值而不是指针地址呢?
9条答案
按热度按时间piwo6bdm1#
当您在源代码中写入“字符串”时,它会直接写入可执行文件,因为需要在编译时知道该值(有一些工具可以把软件拆开,找到其中所有的纯文本字符串)当你写
char *a = "This is a string"
的时候,“这是一个字符串”的位置在可执行文件中,位置a
指向,在可执行文件中。可执行文件映像中的数据是只读的。你需要做的(正如其他答案所指出的)是在一个非只读的位置创建内存--在堆上,或者在堆栈框架中。如果你声明了一个局部数组,那么在堆栈上为数组的每个元素腾出空间,并且字符串字面量(存储在可执行文件中)被复制到堆栈中的那个空间。
您也可以手动复制数据,方法是在堆上分配一些内存,然后使用
strcpy()
将字符串复制到该空间中。无论何时使用
malloc()
分配空间,请记住在完成后调用free()
(请阅读:存储器泄漏)。基本上,你必须跟踪你的数据在哪里。每当你在你的源代码中写入一个字符串时,这个字符串是只读的(否则您可能会更改可执行文件的行为--想象一下,如果您写入
char *a = "hello";
,然后将a[0]
更改为'c'
。然后在其他地方写入printf("hello");
。如果允许更改"hello"
的第一个字符,并且您的编译器只存储了一次(应该如此),那么printf("hello");
将输出cello
!)9rnv2umw2#
不,你不能修改它,因为字符串可以存储在只读存储器中。如果你想修改它,你可以用数组代替。
或者,您可以使用malloc来分配内存,例如:
vzgqcmou3#
很多人对
char*
和char[]
在C中与字符串常量结合使用时的区别感到困惑。...您实际上是将
foo
指向一个常量内存块(实际上,在这种情况下,编译器对"hello world"
的处理取决于实现)。使用
char[]
来告诉编译器你想创建一个数组并用内容填充它,"hello world"
。foo
是指向char
数组的第一个索引的指针。它们都是char
指针,但是只有char[]
会指向本地分配的可变内存块。cedebl8k4#
a & B的内存不是你分配的。编译器可以自由选择一个只读内存位置来存储字符。所以如果你试图改变它可能会导致seg错误。所以我建议你自己创建一个字符数组。类似于:
char a[10]; strcpy(a, "Hello");
h22fl7wq5#
看起来你的问题已经得到了解答,但是现在你可能会想为什么char * a ="String"被存储在只读内存中。实际上,c99标准没有定义它,但是大多数编译器选择这种方式,例如:
c99 standard(pdf) [第130页,第6.7.8节]:
宣言:
定义"plain"字符数组对象s和t,它们的元素是用字符串初始化的。这个声明和char相同
数组的内容是可以修改的。另一方面,声明
定义类型为"字符指针"的p,并将其初始化为指向类型为"字符数组"、长度为4的对象,该对象的元素是用字符串文本初始化的。如果试图使用p修改数组的内容,则行为未定义。
nuypyhwy6#
您也可以使用
strdup
:例如:
wi3ka0sx7#
所有这些都很好地解释了为什么不能修改字符串常量,因为它们被放置在只读内存中。然而,当需要做的时候,有一种方法可以做到这一点。看看这个例子:
我已经将此作为my somewhat deeper thoughts on const-correctness的一部分编写,您可能会觉得有趣(我希望:))。
希望有帮助,祝你好运!
kdfy810k8#
你需要将字符串复制到另一个非只读的内存缓冲区中并在那里修改它,使用strncpy()复制字符串,使用strlen()检测字符串长度,使用malloc()和free()为新字符串动态分配缓冲区。
例如(C++类伪代码):
2vuwiymt9#