2012-02-15 50 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";)。同樣,你需要注意不要在那裏存放任何東西。

相關問題