使用指针修改字符串时发生分段错误?

上下文

我正在学习C,我正在尝试使用指针来反转字符串。 (我知道你可以使用一个数组;这更多的是学习指针。)

问题

尝试运行下面的代码时,我不断遇到分段错误。 GCC似乎不喜欢*end = *begin; 线。 这是为什么?

特别是因为我的代码几乎与另一个问题中讨论的非邪恶C函数相同

 #include  #include  void my_strrev(char* begin){ char temp; char* end; end = begin + strlen(begin) - 1; while(end>begin){ temp = *end; *end = *begin; *begin = temp; end--; begin++; } } main(){ char *string = "foobar"; my_strrev(string); printf("%s", string); } 

传递给函数的参数存在一个问题:

 char *string = "foobar"; 

这是在只读部分中分配的静态字符串。 当您尝试用它覆盖它时

 *end = *begin; 

你会得到段错误。

试试吧

 char string[] = "foobar"; 

你应该注意到一个区别。

关键点在于,在第一种情况下,字符串存在于只读段中,并且仅使用指向它的指针,而在第二种情况下,在堆栈上保留具有适当大小的字符数组和静态字符串(其中永远存在)被复制到其中。 之后,您可以自由修改arrays的内容。

您还可以使用字符串末尾的空字符来交换字符串中的字符,从而避免使用任何额外的空格。 这是代码:

 #include  void reverse(char *str){ int length=0,i=0; while(str[i++]!='\0') length++; for(i=0;i 

在您的代码中,您有以下内容:

 *end--; *begin++; 

只做纯粹的运气,这是正确的事情(实际上,原因是运算符优先)。 看起来你打算让代码真正做到

 (*end)--; (*begin)++; 

这是完全错误的。 你拥有它的方式,操作就像

  • 减少end然后取消引用它
  • 增量begin然后取消引用它

在这两种情况下,取消引用都是多余的,应该删除。 你可能想要的行为

 end--; begin++; 

这些是推动开发人员瘫痪的因素,因为他们很难追查。

这将是适当的并使用指针

  #include #include #include void reve(char *s) { for(char *end = s + (strlen(s) - 1); end > s ; --end, ++s) { (*s) ^= (*end); (*end) ^= (*s); (*s) ^= (*end); } } int main(void) { char *c = malloc(sizeof(char *) * 250); scanf("%s", c); reve(c); printf("\nReverse String %s", c); } 

改变char *string = "foobar"; to char string[] = "foobar"; 。 问题是char *指向只读内存然后尝试修改导致分段错误。

这使得一个小的(ish)递归函数通过将值存储在堆栈的路上并在返回的路上(返回)将指针递增到字符串的开头(* s)来工作。

聪明的代码,但在堆栈使用方面很糟糕。

 #include  char *reverse_r(char val, char *s, char *n) { if (*n) s = reverse_r(*n, s, n+1); *s = val; return s+1; } int main(int argc, char *argv[]) { char *aString; if (argc < 2) { printf("Usage: RSIP \n"); return 0; } aString = argv[1]; printf("String to reverse: %s\n", aString ); reverse_r(*aString, aString, aString+1); printf("Reversed String: %s\n", aString ); return 0; } 

这是我的原地C字符串反转版本。

 #include  #include  int main (int argc, const char * argv[]) { char str[] = "foobar"; printf("String:%s\n", str); int len = (int)strlen(str); printf("Lenth of str: %d\n" , len); int i = 0, j = len - 1; while(i < j){ char temp = str[i]; str[i] = str[j]; str[j] = temp; i++; j--; } printf("Reverse of String:%s\n", str); return 0; } 

下面,您可以看到此问题的代码:

 #include  #include  char* strRev(char* str) { char *first,*last; if (!str || !*str) return str; size_t len = strlen(str); for (first = str, last = &str[len] - 1; first < last ; first++, last--) { str[len] = *first; *first = *last; *last = str[len]; } str[len] = '\0'; return str; } int main() { char test[13] = "A new string"; std::cout << strRev(test) << std::endl; return 0; }