我正在尝试反转一个字符串。
这是我尝试过的代码:
#include<stdio.h>
#include<string.h>
int main(){
char *c="I am a good boy";
printf("\n The input string is : %s\n",c);
printf("\n The length of the string is : %d\n",strlen(c));
int i,j;
char temp;
int len=strlen(c);
for(i=0,j=len-1;i<=j;i++,j--)
{
temp=c[i];
c[i]=c[j];
c[j]=temp;
//printf("%c\t%c\n",*(c+i),*(c+(len-i-1)));
}
printf("\n reversed string is : %s\n\n",c);
}
代码输出Bus error : 10
。
但是如果我重写相同的代码:
int main(void)
{
char *str;
str="I am a good boy";
int i,j;
char temp;
int len=strlen(str);
char *ptr=NULL;
ptr=malloc(sizeof(char)*(len));
ptr=strcpy(ptr,str);
for (i=0, j=len-1; i<=j; i++, j--)
{
temp=ptr[i];
ptr[i]=ptr[j];
ptr[j]=temp;
}
printf("The reverse of the string is : %s\n",ptr);
}
完美无缺。
为什么第一个代码抛出总线错误或分段错误?
答案 0 :(得分:16)
发生总线错误是因为在许多(如果不是大多数或所有现代的)C编译器中,字符串文字都分配在只读存储器中。
您正在将字符串反转到位。在您的第一个代码段中,您尝试写入字符串文字。不是个好主意。
在第二种情况下,你malloc了一个把它放在堆上的字符串。现在可以安全地将该字符串反转到位。
<强>附录强>
对于询问段错误与总线错误的评论者,这是一个很好的问题。我见过两者。这是mac上的总线错误:
$ cat bus.c
char* s = "abc"; int main() {s[0]='d'; return 0;}
$ gcc --version bus.c && ./a.out
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5659)
Copyright (C) 2007 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Bus error
在其他操作系统/编译器上,您可能确实会遇到段错误。
答案 1 :(得分:6)
将其复制到堆是一种选择。但是,如果您只想分配本地(堆栈)数组,则可以执行以下操作:
char str[] = "I am a good boy";
然后,常量字符串将被复制到堆栈中。
答案 2 :(得分:1)
以"I am a good boy"
形式指定的字符数组通常是常量 - 您无法修改它们。这就是你的第一个变种崩溃的原因。第二个不是,因为你复制了数据然后修改它。
答案 3 :(得分:0)
char * str =“我是个好孩子”;作为文字处理并尝试修改它将导致总线错误。它相当于const char * str =“我是一个好孩子”,即指向常量字符串的指针并且不允许尝试修改常量字符串。
编辑:你malloc()和复制的那一刻你正在玩一个原始字符串的副本而ptr不是'const char *'类型,而是'char * ptr'并且没有抱怨。
答案 4 :(得分:0)
使用c ++(g ++)进行编译显示不赞成将字符串文字赋值给非const char *,以防止出现此错误:
ed@bad-horse:~/udlit_debug$ g++ ../buserr.cpp
../buserr.cpp: In function ‘int main()’:
../buserr.cpp:5:13: warning: deprecated conversion from string constant to ‘char*’
../buserr.cpp:7:61: warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘size_t’
相关警告在第5行。
如所指示的那样将声明更改为const char *会阻止分配到文字字符串中。
这也是为什么你不应该忽略警告的一课。