2012-02-15 99 views
6
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不是? 请从这里节省我......为什么scanf在写入字符串文字时无法按预期工作?

+0

我强烈建议阅读这个问题的[C FAQ条目](http://c-faq.com/aryptr/aryptr2.html)。 – Lundin 2012-02-15 10:56:10

+0

这绝对是一个很好的阅读:[char a \ [\] =“string”之间的区别是什么?和char * p =“string”;](http://stackoverflow.com/questions/9460260/what-is-the-difference-between-char-a-string-and-char-p-string) – 2012-05-29 09:32:38

回答

2

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

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

char *a="goodone"; 

char a[]="goodone"; 

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

scanf("%7s",a); 

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

+2

强调这个观点,*从来没有*使用'scanf()',只有'%s'格式。不管你提供多大的缓冲区,你都不能阻止用户输入足够的字符来溢出它。它与'gets()'一样不安全(也不应该使用它)。 – 2012-02-15 10:19:50

+0

@KeithThompson gets()不再是C的标准,因为C11。 – Lundin 2012-02-15 10:58:00

+0

@Lundin:对 - 但大多数或所有的实现仍然提供它(可能带有警告),可悲的是仍然有大量的书籍和教程使用它。 – 2012-02-15 23:52:31

1

char *a只是指向char的指针。当您为其指定"goodone"时,它指向字符串文字(它是只读的),并且scanf会尝试覆盖导致崩溃的内存中的字符串。

如果您将b指定给它,则指向a指向可写入的内存区域(即最大长度为9 +的字符串+终止NUL)。因此,只要scanf不会存储比那里更长的任何东西。

同样,您可以使用a而不是指针(即char a[] = "goodone";)。同样,你需要注意不要在那里存放任何东西。

相关问题