为啥在写入字符串文字时 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个char
s的可写内存区域(即一个最大长度为9的字符串+终止NUL)。因此,只要scanf
没有存储比其中更长的任何内容,它就可以工作。
同样,您可以将a
设为数组而不是指针(即char a[] = "goodone";
)。同样,您需要注意不要在其中存放更长的时间。
【讨论】:
以上是关于为啥在写入字符串文字时 scanf 不能按预期工作? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
为啥当我在 UIHostingController 中使用 SwiftUI-transition 时,它不能按预期工作?