getchar()로 입력받을시 char c가 아닌 int c가 사용되는 이유는?
#include <stdio.h> main() { int c; c = getchar(); while ( c != EOF ){ putchar(c); c=getchar(); } }
unsigned char c로 정의한 경우 EOF(=^Z)가 입력된 경우
무한루프에 빠지는데..
(signed) char c로 정의한 경우 나 int c로 정의한 경우에는
똑같이 ^Z입력시 루프가 종료됩니다...
반드시 int c로 getchar의 리턴값을 받아야 한다는
C programming FAQs의 내용(12.1)가 차이가 나는 것같아 헷갈립니다..
EOF가 integer로 정의 되어 있어서.. char를 써도 되지만...
비교시 형변환이 필요하기 때문에.. int를 권장하는 건가요?
http://www.cinsk.org/cfaqs/html/node14.html#SECTION001410000000000000000Q 12.1
이 코드에서 잘못된 부분이 있나요?char c;
while ((c = getchar()) != EOF) ...Answer
일단, getchar의 리턴 값을 저장하는 변수는 반드시 int이어야 합니다. getchar()는 어떠한 문자 값이나, EOF를 리턴할 수 있습니다. EOF는 int 타입이기 때문에 이 리턴 값을 char에 저장하는 것은 EOF를 잘못 해석하게 할 소지가 있습니다 (특히 char의 타입이 unsigned인 경우 문제가 심각합니다).위의 코드처럼 getchar()의 리턴값을 char에 담을 경우, 두 가지 결과를 예상할 수 있습니다.
* char의 타입이 signed인 경우, 그리고 EOF가 -1로 정의된 경우, 문자 값이 부호 확장(sign extension)되어, 문자값 255가 (C 언어 표현으로 '\377' 또는 '\xff') EOF와 같아집니다. 따라서 입력 도중에 입력 처리가 끝나버릴 수 있습니다.
* char의 타입이 unsigned인 경우, EOF 값이 (상위 비트들이 잘라져 대개 255나 0xff의 값으로) 잘라져서, EOF로 인식이 되지 않아 버립니다. 따라서 이 경우, 무한 루프에 빠져 버립니다.12.3
이 버그는 char가 signed이고, 입력이 모두 7 비트 문자인 경우, 발견하기가 매우 힘듭니다 (char가 signed인지 unsigned인지는 implementation-defined입니다.)
Re: getchar()로 입력받을시 char c가 아닌 int c가 사용되는 이유는?
물론 저 코드는 구현체에 따라서 잘 작동하기도 합니다만 일반적으로는 버그에 해당한다고 볼 수 있습니다. EOF의 요구조건은 "0보다 작을 것"이며 보통 -1을 많이 쓰는데, 저 경우에는 char가 signed라서 getchar가 반환한 EOF가 signed char로 변환되어도 값이 보존되면서 비교에는 문제가 없기 때문입니다. 하지만 C FAQ에서도 언급했듯이 char가 signed인 unsigned는 구현체마다 다르므로 컴파일러에 따라서 문제가 생길 수도 있으므로 (unsigned라면 형변환되면서 값이 바뀌어버리겠죠) 가급적이면 쓰지 말아야 할 코드입니다. 항상 int로 쓰는 습관을 기르세요.
- 토끼군
man page에 써있는 말입니다.[quote]fgetc(), ge
man page에 써있는 말입니다.
음미해 보시면 답이 나올 것입니다.
Re: getchar()로 입력받을시 char c가 아닌 int c가 사용되는 이유는?
이 코드가 버그인 이유는 구현체마다 달라서 char가 signed인지 unsigned인지 모르기 때문이 아닙니다. 어느 경우에도 잘 작동하지 않는 코드이며, 명백한 버그 코드입니다.
getchar의 리턴값이 int인 이유는 fgetwc의 리턴값이 wchar_t가 아니고 wint_t이 이유와 동일합니다. 잘 생각해보세요~ :wink:
Re: getchar()로 입력받을시 char c가 아닌 int c가 사용되는 이유는?
저는 토끼군님의 설명이 맞다고 생각하는데요. char형의 유부호 여부 이외에도
이식성 없는 형변환까지 관련된 문제이긴 합니다만. 많은 경우에 잘 작동하기
때문에 잘못 알고 있는 사람들이 많기도 하고요.
많은 분이 잘못 생각하시고 있는 부분이 있는데, [code:1]char
많은 분이 잘못 생각하시고 있는 부분이 있는데,
char ch = getchar();
의 문제의 원인은 char가 signed인지 unsigned인지와 전혀 관련이 없습니다. 단지 문제의 결과 발생하는 현상이 char가 signed일 때와 unsigned일 때가 다를 뿐입니다.자세히 설명하자면,
정상적인 경우:
맨페이지를 보면 getchar() 함수는 결과값을 unsigned char로 읽어서 int형으로 캐스팅한 결과를 리턴한다고 하고 있습니다. 결과를 제대로 int형으로 받으면 0 ~ 255의 정상적인 결과와 EOF라는 에러를 저장할 수 있습니다.
문제의 원인:
getchar() 함수는 257가지의 결과가 존재합니다. (256가지 정상적 결과 + EOF) 이 범위는 (signed이든 unsigned이든) char 형이 저장할 수 있는 256가지보다 크기 때문에 모든 결과를 받을 수가 없습니다. 즉, 어느 두 결과값은 겹칠 수 밖에 없습니다.
문제의 결과:
에서(EOF가 int형 -1이라 가정합시다)
char이 signed일 때와 unsigned일 때
공통점: 정상적인 결과값 255와 EOF를 구분할 수 없습니다.
차이점:
ch가 signed일 때 - 정상적인 결과값인 255를 받았을 때 EOF를 받은 것과 같이 동작하는 문제가 있습니다.
-> signed char값에 255를 넣으면 -1이 되므로 식이 거짓이 됨
ch가 unsigned일 때 - EOF를 받았을 때 정상적인 결과값인 255를 받은 것과 갈이 동작하는 문제가 있습니다.
-> unsigned char값에 EOF를 넣으면 255가 되므로 식이 참이 됨
결론:
getchar()의 결과는 항상 int형으로 받아야 합니다. char형으로 받는건 언제나 잘못된 코드입이다. char로 받았는데도 잘 돌아갔다면, 다루는 파일에 우연하게도 255에 해당하는 값이 없었을 뿐이죠. 이식성 없는 형변환, char이 내부적으로 signed인지 unsigned인지는 관계가 없습니다.
정리가 되셨기 바랍니다.
[quote="eungkyu"]결론:getchar()의 결과는 항상
네, 맞습니다. getchar()의 반환값을 char로 받아도 좋다고 한 사람은 아무도 없으니
안심하세요. :-) signed/unsigned 얘기가 나온 것도 그것이 원인이라는 뜻이
아니라 부호의 여부에 따라 오류가 발생할 수 있는 상황을 예로 든 것입니다. 잘못
알고 있는 사람이 많으니 FAQ에 올라온 것이고요.
아, 그리고 한 가지 덧붙이면 이식성 없는 형변환이란
을 말한 것입니다.
구현체에 따라 잘 동작할 수도 있다는 얘기에 좀 민감해진거 같네요.
구현체에 따라 잘 동작할 수도 있다는 얘기에 좀 민감해진거 같네요.
우연히 잘 동작하는 경우가 있을 뿐 완전 잘못된 사용이라는 것이라는 것을 강조하고 싶었습니다 :)
("가급적 이렇게 사용하는게 좋습니다"가 아니구요 ^^)
댓글 달기