为啥在写入字符串文字时 scanf 不能按预期工作? [复制]

Posted

技术标签:

【中文标题】为啥在写入字符串文字时 scanf 不能按预期工作? [复制]【英文标题】: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 FAQ entry 来解答这个问题。 这绝对是一本好书:What is the difference between char a[] = “string”; and char *p = “string”; 【参考方案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";)。同样,您需要注意不要在其中存放更长的时间。

【讨论】:

以上是关于为啥在写入字符串文字时 scanf 不能按预期工作? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个正则表达式模式不能按预期工作?

为啥使用 Vue 编辑数据不能按预期工作

为啥当我在 UIHostingController 中使用 SwiftUI-transition 时,它不能按预期工作?

为啥 nodejs 中的睡眠不能按预期工作

为啥 itertools groupby 不能按预期工作? [复制]

为啥这个回滚功能不能按预期工作