修改C字符串常量?

时间:2009-01-26 17:13:01

标签: c string pointers

  

可能重复:
  Why do I get a segmentation fault when writing to a string?

我想写一个函数来反转传递给它的给定字符串。 但是我不能。如果我使用字符数组提供doReverse函数(请参阅下面的代码),我的代码运行良好。

我无法弄清楚为什么这不起作用。 我能够访问str[0]中的doReverse,但我无法使用char指针更改数组的任何值。有什么想法吗?

void doReverse(char *str) {
    str[0] = 'b';
}

void main(void) {
    char *str = "abc";
    doReverse(str);
    puts(str);
}

更新

我知道如何通过将字符数组传递给它来编写反向函数:

void reverse1(char p[]) {
    int i, temp, y;

    for (i = 0, y = strlen(p); i < y; ++i, --y) {
        temp = p[y-1];
        p[y-1] = p[i];
        p[i] = temp;
    }
}

但是,我想写另一个版本,它将char指针作为参数。

5 个答案:

答案 0 :(得分:19)

既然你正在读考试,我会充实我的评论,以解释实际发生的事情:

char *str = "abc";

str是存储在堆栈中的指针。它被初始化为指向文字字符串"abc"。该文字字符串将存储在已编译可执行文件的数据部分中,并在加载程序时加载到内存中。该部分内存是只读的,因此当您尝试修改str指向的数据时,会出现访问冲突。

char* str = malloc(sizeof(char) * 4);
strcpy(str, "abc");

这里,str是与第一个例子相同的堆栈指针。这次,它被初始化为指向堆上的4个字符的内存块,您可以读取和写入。起初,该内存块未初始化,可以包含任何内容。 strcpy读取存储“abc”的只读存储器块,并将其复制到str指向的读写存储器块中。请注意,设置str[3] = '\0'是多余的,因为strcpy已经这样做了。

顺便说一下,如果您在visual studio中工作,请改用strcpy_s,以确保在复制的字符串超出预期时不会覆盖缓冲区。

char str[] = "abc"; 

此处str现在是在堆栈上分配的数组。编译器将使其大小完全符合用于初始化它的字符串文字(包括NULL终止符)。堆栈内存是读写的,因此您可以根据需要修改数组中的值。

char str[4] = "abc";

这与以前的版本实际上是一样的,只是告诉编译器你知道的数据应该比数组的长度更好。如果更改字符串而不是数组大小,则可能会遇到麻烦。

答案 1 :(得分:13)

最简单的解决方案是将str的声明更改为

char str[] = "abc";

这使得str一个char数组,初始化为字符串“abc”。目前,您将str作为指向char的指针进行初始化,以指向由字符串文字描述的字符串。有一个关键的区别:字符串文字是只读的,以便编译器在存储它们的位置具有最大的灵活性;修改它们是UB。但是char数组是可变的,因此可以修改它们。

PS。 main()会返回int

答案 2 :(得分:5)

因为这是作业,我会给出建议,但我不会发布完整的解决方案。

我猜你在str [0] ='b'上遇到了访问冲突? 这是因为“abc”是一个字符串文字。

将字符串str points复制到调用reverse之前,或者反向调用以分配缓冲区并将反向字符串放入其中。

请记住,您必须释放所有分配的内存。

答案 3 :(得分:5)

Lordy,Lordy。对于那些建议实际进行交换的人,请仔细阅读问题;没有什么比重申一个已经非常明确的问题更糟的了。无论用于实现交换的方法(临时交换,xor3交换等),这个人似乎都非常熟悉函数的基本内容和相当基本的内在函数。

然而,正如已经解释的那样,编译器/链接器通常将所有字符串文字放在目标可执行文件的“const数据段”中,随后在适当的“load / exec”期间与不可写的MMU描述符相关联。调用。随后通过此描述符发出的所有CPU写周期都会被MMU的异常机制自动捕获,从而产生强制性的“段错误”或特定于平台的等价物。当然,不言而喻,较旧的非MMU平台不会出现这种行为。

虽然这有效地获得了对源语言的“常量/文字”习惯的运行时支持,但是历史上有几个平台促进了显式编译时段覆盖。然而,这种支持水平逐渐减弱,有利于更严格/更强大的抽象层,从而使许多明显且通常有用的优化变得难以理解。随着时间和磨损逐渐老化“MC / ASM”理念,在一个过于热切的“微软”一代之前,程序员不再被认为具有足够的知识或负责任以做出这种决定。代替我作为项目负责人目睹的许多人为的,而不是创造性的实施,这绝不是一件坏事。

尽管这篇文章正在迅速演变成一个偏离主题的违规行为,但我仍然感到有些自上而下的相关问题在我们的行业中慢慢流行起来。作为一个初出茅庐的C程序员 - 一种最初旨在补充低级开发的语言 - 我的建议是采用自下而上的方法,并通过一些课外汇编语言开发来增强你的学习。由于算法实现可能构成您作为应用工程师的主要关注点,因此重要的是要记住当代CPU设计在过去30年中经历了均匀演变;今天的超快速英特尔CPU只不过是我在地球还很年轻的时候编程的4/8位双极性处理器的超标量CMOS改进。

与流行的看法相反,汇编语言编程相对容易学习,并且在尝试协调高级构造与有问题或深奥的行为时绝对必要。一旦你考虑了无数个小时的实验,调试,网络搜索和论坛垃圾邮件,毫无疑问,自下而上的方法肯定是阻力最小的途径。

祝你学习顺利。

答案 4 :(得分:1)

据我所知,常量字符串是作为常量字符数组实现的(或者,用C语言表示const char [length])。因此,您无法修改其字符。

尝试动态分配字符串。

char* str = (char*)malloc(sizeof(char) * 4);
strcpy(str, "abc");
str[3] = '\0';

当然,不要忘记在程序结束时释放内存。


编辑:我不会发布与翻转字符串有关的任何内容,因为这是你的工作。