2012-02-15 4 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 * (할당 한 = b (주석 처리 됨)) 메모리를 예약하면 정상적으로 작동합니다. 그렇지 않으면 그렇지 않습니다. char * a는 문자열에 메모리를 할당하고 그 메모리 위치를 값으로 반환한다고 생각합니다. 그리고 printf는 왜 scanf가 아닌지이 믿음으로 잘 작동합니까? 나를 구 해주십시오.문자열 리터럴에 쓸 때 scanf가 예상대로 작동하지 않는 이유는 무엇입니까?

+0

이 질문에 대해서는 [C FAQ 항목] (http://c-faq.com/aryptr/aryptr2.html)을 읽기를 강력히 권장합니다. – Lundin

+0

이것은 확실히 좋은 읽을 거리입니다. [char a \ [\] = "string"의 차이점은 무엇입니까? 및 char * p = "string";] (http://stackoverflow.com/questions/9460260/what-is-the-difference-between-char-a-string-and-char-p-string) –

답변

2

scanf에게 읽어 들인 데이터를 const char* 값으로 할당 된 메모리, 즉 읽기 전용 메모리에 쓰도록 지시하기 때문입니다.

당신이 당신의 문자열 상수를 쓰기 가능하게이 중 안전 아니라고

char *a="goodone"; 

char a[]="goodone"; 

주를 변경하려면 : 사용자가 7 개 이상의 문자를 입력 할 때 충돌이 발생할 수 있습니다 . 해당 문제를 해결하려면 형식 지정자에 한도를 추가하십시오.

scanf("%7s",a); 

P.S. 문자열 상수를 수정하지 않기 때문에 주석 처리 된 a=b이 제대로 작동합니다. 오히려 포인터을 문자 상수로 수정합니다. 입니다.

+2

강조하려면 * 절대 사용하지 않는'% s' 형식의'scanf()'를 사용하십시오. 아무리 큰 버퍼를 제공하더라도 사용자가 오버플로 할만큼 충분한 문자를 입력하는 것을 막을 수는 없습니다. 그것은 gets() (결코 사용되어서는 안됩니다)만큼 안전하지 않습니다. –

+0

@KeithThompson gets()는 C11 이후 더 이상 표준 C가 아닙니다. – Lundin

+0

@ Lundin : 맞습니다. - 그러나 대부분의 또는 모든 구현체는 여전히 (경고와 함께) 그것을 제공하고 있으며, 슬프게도 그것을 사용하는 책과 튜토리얼이 많이 남아 있습니다. –

1

char *achar에 대한 포인터 일뿐입니다. "goodone"을 지정하면 해당 문자열 리터럴 (읽기 전용)을 가리키며 scanf은 충돌을 일으키는 메모리의 해당 문자열을 덮어 쓰려고합니다.

이를 b에 할당하면, 다음 10 char s의 기록 가능한 메모리 영역에 포인팅 a있다 (즉, 최대 길이의 문자열 9 + 착신 NUL). 따라서 scanf이 거기에있는 것보다 오래 저장되지 않는 한 작동합니다.

마찬가지로 포인터 대신 배열 a을 만들 수 있습니다 (즉, char a[] = "goodone";). 다시 거기에 더 이상 아무것도 저장하지 않도록 조심해야합니다.

관련 문제