2012-02-15 49 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); 

} 

Tại sao tính năng này không hoạt động? Tôi đã thử rất nhiều với scanf này, nhưng, khi tôi dự trữ bộ nhớ cho biến của tôi một * (bằng cách gán một = b (nhận xét)) nó hoạt động tốt. Nếu không thì không. Tôi tin rằng char * a sẽ cấp phát một số bộ nhớ cho chuỗi của nó, ("goodone") và trả về vị trí bộ nhớ đó với giá trị của nó. Và printf làm việc tốt với niềm tin này tại sao scanf không? hãy lưu tôi khỏi điều này ....Tại sao scanf không hoạt động như mong đợi khi ghi vào chuỗi ký tự?

+0

Tôi đặc biệt khuyên bạn nên đọc [C FAQ entry] (http://c-faq.com/aryptr/aryptr2.html) cho câu hỏi này. – Lundin

+0

Điều này chắc chắn là một đọc tốt: [Sự khác biệt giữa char a \ [\] = "string"; và char * p = “string”;] (http://stackoverflow.com/questions/9460260/what-is-the-difference-between-char-a-string-and-char-p-string) –

Trả lời

2

Điều này là do bạn đang hướng dẫn scanf để ghi dữ liệu mà nó đọc vào bộ nhớ được phân bổ cho giá trị const char*, tức là vào bộ nhớ chỉ đọc.

Nếu bạn muốn thực hiện chuỗi của bạn có thể ghi liên tục, thay đổi

char *a="goodone"; 

để

char a[]="goodone"; 

Lưu ý rằng điều này không an toàn hoặc là: nó có thể sụp đổ khi người dùng nhập vào hơn bảy ký tự . Thêm giới hạn vào trình định dạng định dạng của bạn để giải quyết vấn đề đó:

scanf("%7s",a); 

P.S. Các nhận xét ra a=b hoạt động tốt bởi vì nó không phải là sửa đổi chuỗi liên tục; thay vào đó, nó sửa đổi con trỏ thành hằng số ký tự, trong đó được phép.

+2

Để nhấn mạnh điểm, * không bao giờ * sử dụng 'scanf()' với định dạng '% s' trống. Cho dù bạn có cung cấp bộ đệm lớn đến mức nào, bạn cũng không thể ngăn người dùng nhập đủ ký tự để tràn bộ đệm đó. Nó không an toàn như 'gets()' (cũng không bao giờ được sử dụng). –

+0

@KeithThompson được() không còn là tiêu chuẩn C, kể từ C11. – Lundin

+0

@Lundin: Đúng - nhưng hầu hết hoặc tất cả các triển khai vẫn cung cấp nó (có lẽ với cảnh báo), và thật đáng buồn là vẫn còn rất nhiều sách và hướng dẫn sử dụng nó. –

1

char *a chỉ là một con trỏ đến char. Khi bạn chỉ định "goodone" cho nó, nó trỏ đến chuỗi chữ đó (chỉ đọc), và scanf cố gắng ghi đè lên chuỗi đó trong bộ nhớ gây ra sự cố.

Nếu bạn gán b cho nó, sau đó bạn có a trỏ đến khu vực bộ nhớ có thể ghi 10 char s (tức là, chuỗi có độ dài tối đa 9 + kết thúc NUL). Vì vậy, nó hoạt động miễn là scanf không lưu trữ bất cứ điều gì dài hơn trong đó.

Tương tự, bạn có thể làm cho a một mảng thay vì một con trỏ (ví dụ: char a[] = "goodone";). Một lần nữa bạn cần phải xem ra không để lưu trữ bất cứ điều gì lâu hơn trong đó.

Các vấn đề liên quan