尝试使用scanf中的数据时出现SEGFULT?

尝试使用scanf中的数据时出现SEGFULT?,c,segmentation-fault,scanf,C,Segmentation Fault,Scanf,我真的很难理解是什么导致了这个问题,我真的很想了解幕后发生了什么,让这个问题发生。下面的代码旨在获取最大长度为99个字符的字符串,将其放入一个名为word的变量中,然后读取长度;稍后我将根据字符串中的字符数量重新分配分配给它的内存,但现在我只想能够获得输入。以下是代码段: char* word = malloc(100); printf("Enter a string:\n"); int x = scanf("%s", &word); printf("Length = %d", x);

我真的很难理解是什么导致了这个问题,我真的很想了解幕后发生了什么,让这个问题发生。下面的代码旨在获取最大长度为99个字符的字符串,将其放入一个名为word的变量中,然后读取长度;稍后我将根据字符串中的字符数量重新分配分配给它的内存,但现在我只想能够获得输入。以下是代码段:

char* word = malloc(100);
printf("Enter a string:\n");
int x = scanf("%s", &word);
printf("Length = %d", x);
printf("Word is %s", word);
使用时,会发生以下情况:

Enter a string:
123
1
Segmentation Fault
这里发生了什么事?为什么这不起作用?我认为用malloc分配内存会给它足够的空间,然后scanf会将我的字放入变量中?我需要使用malloc,因为我需要在以后realloc,以避免使用比以后需要的内存更多的内存。

在您的代码中

 int x = scanf("%s", &word);
应改为

 int x = scanf("%99s", word); //99 chars to be scanned - at max - see note below
由于
word
已经是指向
char
的指针,因此

  • %s
  • 指向您刚才分配的内存
引用
fscanf()
系列的
C11
,第§7.21.6.2章

s

[…]如果不存在
l
长度修饰符,则相应的参数应为a 指向字符数组的初始元素的指针,该元素的大小足以接受 序列和一个将自动添加的终止空字符。[……]

注意:当有疑问/困惑时,务必检查数据类型

  • word
    的类型为
    char*
    ——正确且预期的类型
  • &word
    属于
    char**
    -类型错配
也就是说,有几点建议

  • 始终检查库函数是否成功执行/返回。(
    malloc()
    scanf()
    等),然后再使用结果
  • 始终限制扫描大小,以防止过长的输入导致缓冲区溢出

    • 问题就在这里:
      intx=scanf(“%s”和&word)。不要盲目地将
      scanf一起使用。确实,您应该将地址传递给
      scanf
      ,但这里您传递的是
      word
      的地址。变量
      word
      本身就是一个地址(或者更确切地说,包含一个地址)。您希望从该地址开始写入数据


      放下
      &
      。使用
      intx=scanf(“%s”,单词)

      查看您的代码片段:

      char* word = malloc(100);
      printf("Enter a string:\n");
      int x = scanf("%s", &word);
      
      问题就在我引用的最后一行
      scanf()
      需要一个指向
      %s
      char
      数组的指针。但是,使用运算符的地址(
      &
      )会获取指针的地址,因此您将给
      scanf()
      一个指向指针的指针
      word
      。这是未定义的行为
      scanf()
      只会覆盖指针
      word
      (从而破坏它)——可能会发生其他奇怪的事情。简单的解决方案:删除
      &

      尽管如此,上面的代码并不是全部错误,下面一行:

      int x = scanf("%s", word);
      
      还具有未定义的行为。这是因为您永远无法保证输入的前99个字符中会有空格,因此此代码可能会使缓冲区溢出。对于
      scanf()
      到字符串的转换,始终使用字段宽度,如下所示:

      int x = scanf("%99s", word);
      

      最后,对于固定且相当小的内存量,实际上不需要动态分配它(而且我看不到您会按需要调用
      free()
      )。只需将第一行替换为

      char word[100];
      

      您仍然可以用相同的方式编写其余的代码。在大多数上下文中,数组的标识符的计算结果是指向第一个元素的指针,例如,当将其传递给函数时。

      问题在于此语句
      int x=scanf(“%s”和&word)
      。您已经声明了
      char*word=malloc(100)
      ,这意味着它是一个字符数组。您可以将语句修改为
      int x=scanf(“%s”,word)
      (不带
      &
      )。 检查下面的示例代码:

      传递
      word
      本身为数组的第一个元素提供地址,以存储读取的值

      话虽如此,如果您需要的内存量在编译时就已经知道,那么最好静态分配内存,如下所示:

      char-word[100]

      要读取指定数量的字符,请使用表达式
      scanf(“%s”),
      。在您的情况下,它将是:

      scanf(“%99s”,word)


      这里提供的示例代码:

      可能重复的
      int x=scanf(“%s”和&word);
      ->
      int x=scanf(“%s”,word);
      @ChrisTurner这是一个很好的链接,但是你确定这是一个重复吗?@PaulR我也有一个问题,为什么不需要在
      malloc(100*sizeof(char))中编写呢
      我们需要一个100字符长的字符串吗?@Alan
      sizeof(char)
      被标准定义为
      1
      。你能帮我理解为什么需要这样做吗?这是因为字符串在C中的工作方式(字符数组)或者?这实际上是有道理的,所以如果我已经将变量定义为指针,我不需要在scanf函数中使用-,太好了!@PixelRain是的,我想你明白了,@PixelRain你可能应该读一读你的C教科书中关于指针的章节。