debugging 在C语言中可以修改字符串吗?

cl25kdpy  于 2023-03-03  发布在  其他
关注(0)|答案(9)|浏览(173)

我已经花了几个小时阅读各种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.

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

piwo6bdm

piwo6bdm1#

当您在源代码中写入“字符串”时,它会直接写入可执行文件,因为需要在编译时知道该值(有一些工具可以把软件拆开,找到其中所有的纯文本字符串)当你写char *a = "This is a string"的时候,“这是一个字符串”的位置在可执行文件中,位置a指向,在可执行文件中。可执行文件映像中的数据是只读的。
你需要做的(正如其他答案所指出的)是在一个非只读的位置创建内存--在堆上,或者在堆栈框架中。如果你声明了一个局部数组,那么在堆栈上为数组的每个元素腾出空间,并且字符串字面量(存储在可执行文件中)被复制到堆栈中的那个空间。

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!)

9rnv2umw

9rnv2umw2#

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

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
vzgqcmou

vzgqcmou3#

很多人对char*char[]在C中与字符串常量结合使用时的区别感到困惑。

char *foo = "hello world";

...您实际上是将foo指向一个常量内存块(实际上,在这种情况下,编译器对"hello world"的处理取决于实现)。
使用char[]来告诉编译器你想创建一个数组并用内容填充它,"hello world"foo是指向char数组的第一个索引的指针。它们都是char指针,但是只有char[]会指向本地分配的可变内存块。

cedebl8k

cedebl8k4#

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

h22fl7wq

h22fl7wq5#

看起来你的问题已经得到了解答,但是现在你可能会想为什么char * a ="String"被存储在只读内存中。实际上,c99标准没有定义它,但是大多数编译器选择这种方式,例如:

printf("Hello, World\n");

c99 standard(pdf) [第130页,第6.7.8节]:
宣言:

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

定义"plain"字符数组对象s和t,它们的元素是用字符串初始化的。这个声明和char相同

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

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

char *p = "abc";

定义类型为"字符指针"的p,并将其初始化为指向类型为"字符数组"、长度为4的对象,该对象的元素是用字符串文本初始化的。如果试图使用p修改数组的内容,则行为未定义。

nuypyhwy

nuypyhwy6#

您也可以使用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");
wi3ka0sx

wi3ka0sx7#

所有这些都很好地解释了为什么不能修改字符串常量,因为它们被放置在只读内存中。然而,当需要做的时候,有一种方法可以做到这一点。看看这个例子:

#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;
}

我已经将此作为my somewhat deeper thoughts on const-correctness的一部分编写,您可能会觉得有趣(我希望:))。
希望有帮助,祝你好运!

kdfy810k

kdfy810k8#

你需要将字符串复制到另一个非只读的内存缓冲区中并在那里修改它,使用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;
2vuwiymt

2vuwiymt9#

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);

相关问题