【问题标题】:Could anyone help me to understand this strchr() C Segmentation fault?谁能帮我理解这个 strchr() C 分段错误?
【发布时间】:2017-05-12 20:44:24
【问题描述】:

我正在深入研究 C 中的指针和字符串,但我仍然习惯了一些概念。我尝试实现strchr() 函数的一个版本——与 string.h 中的函数相同——用于学习目的,但一些基本的东西仍然不正确。

这是我的代码:

#include <stdio.h>

char* my_strchr(const char* str, int c){
  if (str == NULL){
    printf("STR is NULL. Finishing the program\n");
    return NULL;
  }
  while (*str != '\0'){
    if (*str == c){
      return (char*) str;
    }
    str++;
  }
  return NULL;
}

int main(){
  char *a = "Hello World!";
  char *b;
  char c;

  printf("Type the character you want to find in the Hello World! string:\n");
  scanf(" %c", &c);

  b = my_strchr(a, c);

  printf("Character found! %c\n", *b);

  return 0;
}

我试图弄清楚为什么这会返回分段错误。当我使用 gbd 时,它告诉我错误在最后一个 printf,它试图打印 *b

一旦my_strchr() 返回(char*) str,我就必须将此返回值存储在char 指针变量中,对吧?

【问题讨论】:

  • 所有输入都会出现这种情况,还是只出现在测试字符串中没有出现的字符?
  • @Rad Lexus 与所有输入...仍在试图弄清楚发生了什么...
  • 显示您的输入。 strchr也可以搜索'\0'
  • 不适用于“所有输入”。输入e 有效。但是当没有找到时,你不会在引用NULL之前测试返回值。
  • 我刚试过。只要您不搜索不在字符串中的字符,它确实 起作用。如果这样做,您将尝试打印NULL 的内容。

标签: c pointers segmentation-fault strchr


【解决方案1】:

my_strchr在字符串中没有找到字符时,返回NULL

在这种情况下 bNULL 所以 *b 是未定义的行为,这解释了段错误。

您可能想在打印*b 之前检查my_strchr 的结果,例如:

if (b != NULL) {
  printf("Character found! %c\n", *b);
} else {
  printf("Not found...\n");
}

【讨论】:

  • 非常感谢您的回答,这就是问题所在!我解决了它,添加了一个 if 语句来测试 b 是否为 NULL,现在就像一个魅力!谢谢大家!
【解决方案2】:

tuple_cat 说的有些逻辑问题。

但我也认为您不了解某些概念,从我的角度来看,您的代码并不干净。

我猜你刚开始用 c 编码,所以继续编码 :)

首先你在你的函数中返回一个 char* 但你将函数的参数定义为

char* my_strchr(const char* str, int c)

在标准 C 中,你不能触及一个不能修改它的常量,这就是声明常量的关键。

所以把函数改成

char* my_strchr(char* str, int c)

那么从字符串返回char的正确方法不是

return (char*)str;

只是

return str;

在你的函数结束时。

这样您将发送 char*(字符串)中第一个字符的地址。 在 char* 中,您只需提供变量名称即可。

我鼓励您阅读:https://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html

实时调频!!! 1.3.4 字符串常量中的 char* 部分

祝你学习顺利。

【讨论】:

  • 谢谢@Raphael,我会继续研究的。无论如何,我所遵循的参考表明,当将字符串作为参数传递时,函数参数应该是一个常量,以避免对字符串进行任何修改。
  • 是的,如果你不修改它。但是返回一个 char* 有什么意义呢?如果你不对它做任何事情,你可以检查它是否做了一些可以返回的事情。 void 或其他,但是是的,它只是为了避免编译器警告,这是推荐的。
  • 这只是关于const-正确性的坏建议。您应该阅读标准库版本的函数原型:strchr(const char *string, int c)。在这种情况下,const表示存储在string指向的位置的值不能被修改;但是可以修改指针本身的值(例如,循环遍历字符串)。在模拟库函数时,最好坚持标准原型并尝试理解为什么要这样写。 OP 正在这样做。
  • 另外,我建议阅读C Standard 以供参考。该标准确实讨论了库要求。您还应该阅读手册以了解您正在使用的任何标准库实现。对于 gcc,这里是 manual for glibc
  • @DavidBowling 我在没有编译器警告的情况下做了应该做的事情,但感谢您的建议,我也会检查一下。
猜你喜欢
  • 2020-10-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多