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

我已经挣扎了好几个小时的各种与指针相关的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. 

那么是否有任何方法来改变字符串内的值,而不是指针地址?

谢谢

编辑:

感谢大家的答案。 现在更有意义了。 特别有意义的是,为什么有时候它工作的很好,有时候不能工作。 因为有时我会通过一个字符指针和其他时间一个字符数组(char数组工作正常)。

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

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

 char a[] = "This is a string"; 

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

 char *a = malloc(256); strcpy(a, "This is a string"); 

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

基本上,你必须跟踪你的数据在哪里。 每当你在你的源代码中写一个字符串时,这个字符串是只读的(否则你可能会改变可执行文件的行为 – 试想如果你写了char *a = "hello";然后把a[0]改为'c'然后在别的地方写了printf("hello");如果允许改变"hello"的第一个字符,并且你的编译器只存储一次(应该),那么printf("hello");会输出cello !)

不,你不能修改它,因为字符串可以存储在只读存储器中。 如果你想修改它,你可以使用一个数组来代替

 char a[] = "This is a string"; 

或者,你可以使用malloc来分配内存

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

很多人对char *和char []与C中的字符串文字之间的差异感到困惑。当你写:

 char *foo = "hello world"; 

…你实际上是把foo指向一个不断的内存块(实际上,编译器在这个例子中用“hello world”做的是依赖于实现的)。

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

a&b的内存不是由您分配的。 编译器可以自由选择一个只读的内存位置来存储字符。 所以如果您尝试更改它可能导致seg故障。 所以我建议你自己创建一个字符数组。 类似于: char a[10]; strcpy(a, "Hello"); char a[10]; strcpy(a, "Hello");

这似乎是你的问题已经回答,但现在你可能想知道为什么char * a =“String”被存储在只读存储器中。 那么,它实际上是由c99标准没有定义,但大多数编译器选择这样的例子如下:

 printf("Hello, World\n"); 

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

声明:

 char s[] = "abc", t[3] = "abc"; 

定义“简单的”字符数组对象s和t,其元素用字符串文字初始化。 这个声明与char相同

 s[] = { 'a', 'b', 'c', '\0' }, t[] = { 'a', 'b', 'c' }; 

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

 char *p = "abc"; 

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

你也可以使用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). 

举个例子:

 char *a = strdup("stack overflow"); 

所有的答案都是很好的解释,为什么你不能修改字符串,因为它们被放在只读存储器中。 然而,当推动推动时,有一种方法可以做到这一点。 看看这个例子:

 #include <sys/mman.h> #include <unistd.h> #include <stddef.h> #include <string.h> #include <stdlib.h> #include <stdio.h> int take_me_back_to_DOS_times(const void *ptr, size_t len); int main() { const *data = "Bender is always sober."; printf("Before: %s\n", data); if (take_me_back_to_DOS_times(data, sizeof(data)) != 0) perror("Time machine appears to be broken!"); memcpy((char *)data + 17, "drunk!", 6); printf("After: %s\n", data); return 0; } int take_me_back_to_DOS_times(const void *ptr, size_t len) { int pagesize; unsigned long long pg_off; void *page; pagesize = sysconf(_SC_PAGE_SIZE); if (pagesize < 0) return -1; pg_off = (unsigned long long)ptr % (unsigned long long)pagesize; page = ((char *)ptr - pg_off); if (mprotect(page, len + pg_off, PROT_READ | PROT_WRITE | PROT_EXEC) == -1) return -1; return 0; } 

我已经写了这个作为我在const正确性 ,你可能会发现有趣的(我希望:)) 更深层次的思考的一部分。

希望它有帮助。 祝你好运!

您需要将字符串复制到另一个,而不是只读的内存缓冲区,并在那里修改它。 使用strncpy()复制字符串,strlen()用于检测字符串长度,malloc()和free()用于为新字符串动态分配缓冲区。

例如(C ++像伪代码):

 int stringLength = strlen( sourceString ); char* newBuffer = malloc( stringLength + 1 ); // you should check if newBuffer is 0 here to test for memory allocaton failure - omitted strncpy( newBuffer, sourceString, stringLength ); newBuffer[stringLength] = 0; // you can now modify the contents of newBuffer freely free( newBuffer ); newBuffer = 0; 
 char *a = "stack overflow"; char *b = "new string, it's real"; int d = strlen(a); b = malloc(d * sizeof(char)); b = strcpy(b,a); printf("%s %s\n", a, b);