c - 在 C 中反转字符串

标签 c string undefined-behavior

我知道这个问题已被问过数千次,但我就是找不到我的代码中的错误。有人可以指出我做错了什么吗?

#include <stdlib.h>
#include <string.h>

void reverseString(char *myString){
  char temp;
  int len = strlen(myString);

  char *left = myString;
  //  char *right = &myString[len-1];                                                                                        
  char *right = myString + strlen(myString) - 1;

  while(left < right){
    temp = *left;
    *left = *right; // this line seems to be causing a segfault                                                              
    *right = temp;
    left++;
    right--;
  }
}

int main(void){
  char *somestring = "hello";
  printf("%s\n", somestring);
  reverseString(somestring);

  printf("%s", somestring);

}

最佳答案

最终,原地反转会更干净,如下所示:

#include <stdio.h>
#include <string.h>

void
reverse(char *s)
{
    int a, b, c;
    for (b = 0, c = strlen(s) - 1; b < c; b++, c--) { 
        a = s[b]; 
        s[b] = s[c]; 
        s[c] = a; 
    }

    return; 
}

int main(void)
{
    char string[] = "hello";
    printf("%s\n", string);
    reverse(string);
    printf("%s\n", string);

    return 0;
}

您的解决方案本质上是这个解决方案的语义放大版本。理解指针和数组之间的区别。该标准明确指出这种操作的行为(修改字符串文字的内容)是未定义的。您还应该看到 this摘自爱斯基摩人:

当您使用字符串常量初始化字符数组时:

char string[] = "Hello, world!";

您最终得到一个包含字符串的数组,您可以根据自己的喜好修改数组的内容:

string[0] = 'J';

但是,可以在代码的其他地方使用字符串常量(正式术语是字符串文字)。因为它们是数组,所以当它们在表达式中使用时,编译器会像往常一样生成指向它们第一个元素的指针。也就是说,如果你说

char *p1 = "Hello";
int len = strlen("world");

就好像你说的一样

char internal_string_1[] = "Hello";
char internal_string_2[] = "world";
char *p1 = &internal_string_1[0];
int len = strlen(&internal_string_2[0]);

在这里,名为 internal_string_1 和 internal_string_2 的数组应该暗示这样一个事实,即每次您在代码中使用字符串常量时,编译器实际上都会生成一些临时数组。然而,一个微妙的事实是,字符串常量“后面”的数组不一定是可修改的。特别是,编译器可以将它们存储在只读存储器中。因此,如果你写

char *p3 = "Hello, world!";
p3[0] = 'J';

您的程序可能会崩溃,因为它可能会尝试将一个值(在本例中为字符“J”)存储到不可写内存中。

寓意是无论何时构建或修改字符串,都必须确保构建或修改它们的内存是可写的。该内存应该是您分配的数组,或者是您通过我们将在下一章中看到的技术动态分配的一些内存。确保你的程序的任何部分都不会尝试修改一个字符串,它实际上是编译器为你生成的未命名的、不可写的数组之一,以响应你的字符串常量之一。 (唯一的异常(exception)是数组初始化,因为如果你写入这样的数组,你是在写入数组,而不是你用来初始化数组的字符串文字。)“

关于c - 在 C 中反转字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2345584/

相关文章:

C - 顶级进程和底层(叶)进程之间的命名管道

c - C 中的三重斜杠注释?

c - 段错误,大型数组

c++ - 是否从任何被视为未定义行为的整数中减去 INT_MIN?

c - 是否使用未初始化的值调用 `wait` 未定义行为?

c - rand() 函数行为

java - 如何将字符串转换为 CharSequence?

python - 从包含键值对的字符串中获取 python 字典

java - 对字符串的特定部分进行二分查找

variables - Lua - 两个同名的局部变量