3

我的代码段错误,我不知道为什么。

 1  #include <stdio.h>
 2
 3  void overwrite(char str[], char x) {
 4    int i;
 5    for (i = 0; str[i] != '\0'; i++)
 6      str[i] = x;
 7  }
 8
 9  int main(void) {
10    char *s = "abcde";
11    char x = 'X';
12    overwrite(s, x);
13    printf("%s\n", s);
14    return 0;
15  }

gdb 调试器告诉我,问题出在第 6 行,我想将一个字符存储到 c 字符串中(如果我使用左值指针解引用,这是同样的问题。)这就是他所说的:

(gdb) run
Starting program: /tmp/x/x 

Breakpoint 1, overwrite (str=0x8048500 "abcde", x=88 'X') at x.c:5
5         for (i = 0; str[i] != '\0'; i++)
(gdb) s
6           str[i] = x;
(gdb) 

Program received signal SIGSEGV, Segmentation fault.
0x080483e3 in overwrite (str=0x8048500 "abcde", x=88 'X') at x.c:6
6           str[i] = x;
(gdb) q

我正在从 K&R-C 书中学习,这是第 2.8 章中的简化示例(删除功能)。我不知道问题出在哪里。

4

5 回答 5

17

因为 char*s = "abcde"; 在只读内存中创建字符串。尝试

char s[] = "abcde";

编辑:解释:char* 是指针,“abcde”是在只读内存中创建的-> 不可变的。

char[] 是数组,它完全存储在堆栈中并从内存中初始化,因此是可变的

于 2009-09-10T14:29:27.347 回答
2

当您定义指向字符串文字的指针时,将其声明为const char *.

const char *s = "abcde";

这样,当您尝试将该字符串发送到 overwrite() 函数时,您的编译器就会报错。

const char *s = "abcde";
char t[] = "fghij";
char x = 'X';

overwrite(s, x); /* oops */
overwrite(t, x); /* ok */
于 2009-09-10T14:54:26.337 回答
1

不是不同意,只是为了详细说明:考虑一下如果编译器允许这样做会发生什么。你可以写:

char *s1="abcde";
char *s2="abcde";
s1[0]='x';
puts(s1);
puts(s2);

如果编译器识别出这两个文字是相同的并重新使用它们,但也允许第 3 行,那么您的输出将是:

xbcde
xbcde

这可能不是您想要的。如果这两个文字位于程序的广泛分离的部分中,这将特别神秘。

于 2009-09-10T15:10:35.943 回答
-1

试用:

#include <iostream>
#include <cstring>

using namespace std;

void overwrite(char[], char);

int main(void)
{
        char *s = strdup("abcde");
        char X = 'X';
        overwrite(s, X);
        cout << s << endl;

        if(s!=NULL)
                delete [] s;

        return 0;
}

void overwrite(char str[], char x)
{
        for(int i=0; str[i]!='\0'; i++)
                str[i] = x;
}
于 2009-09-10T15:11:59.093 回答
-2

我的猜测是您将类型定义为字符数组的参数定义。当您将指针传递给 char 时

您可以尝试将第一行更改为:

 void overwrite(char *str, char x) {

char 数组和 char 指针在语义上是不同的。

于 2009-09-10T14:31:04.617 回答