【问题标题】:Why is scanf not working as expected when writing to a string literal? [duplicate]为什么在写入字符串文字时 scanf 不能按预期工作? [复制]
【发布时间】:2012-03-06 16:11:23
【问题描述】:
include<stdio.h>
int main()
{
    //char b[10];
    char *a="goodone";
    //a=b;

    scanf("%s",a);//this scanf fails and thow segmentation fault.
    printf("%s",a);

} 

为什么这不起作用?我用这个 scanf 做了很多尝试,但是当我为我的变量 a*(通过分配 a=b(注释))保留内存时,它工作正常。否则不会。 我相信 char *a 会为其字符串分配一些内存,(“goodone”)并将该内存位置返回为其值。 printf 在这种信念下工作得很好,为什么 scanf 不行? 请救救我……

【问题讨论】:

标签: c scanf


【解决方案1】:

这是因为您指示scanf 将其读取的数据写入为const char* 值分配的内存中,即写入只读内存中。

如果你想让你的字符串常量可写,改变

char *a="goodone";

char a[]="goodone";

请注意,这也不安全:当用户输入超过七个字符时,它可能会崩溃。为您的格式说明符添加限制以解决该问题:

scanf("%7s",a);

附:注释掉的a=b 工作正常,因为它没有修改字符串常量;相反,它将指针修改为字符常量,允许的。

【讨论】:

  • 为了强调这一点,永远不要使用 scanf() 和纯 %s 格式。无论您提供多大的缓冲区,您都无法阻止用户输入足够的字符以使其溢出。它和gets() 一样不安全(也不应该使用)。
  • @KeithThompson gets() 不再是标准 C,因为 C11。
  • @Lundin:是的——但大多数或所有实现仍然提供它(可能带有警告),遗憾的是仍然有很多书籍和教程使用它。
【解决方案2】:

char *a 只是一个指向char 的指针。当您将 "goodone" 分配给它时,它会指向该字符串文字(它是只读的),并且 scanf 会尝试覆盖内存中导致崩溃的该字符串。

如果你给它分配b,那么你有a指向一个10个chars的可写内存区域(即一个最大长度为9的字符串+终止NUL)。因此,只要scanf 没有存储比其中更长的任何内容,它就可以工作。

同样,您可以将a 设为数组而不是指针(即char a[] = "goodone";)。同样,您需要注意不要在其中存放更长的时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-17
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-24
    • 2012-06-17
    • 2022-11-07
    相关资源
    最近更新 更多