문자 유형으로 EOF (파일 끝) 문자 저장


11

나는 Dennis Ritchie의 C Programming Language 책에서 intEOF를 보유하기 위해 변수에 사용되어야합니다 char. EOF 값을 보유 할 수있을만큼 충분히 커야 합니다. 그러나 다음 코드는 정상적으로 작동합니다.

#include<stdio.h> 

main()  { 
  char c; 
  c=getchar(); 
  while(c!=EOF)  { 
    putchar(c); 
    c=getchar(); 
  } 
} 

더 이상 입력이 없으면 getcharEOF를 반환합니다. 위의 프로그램에서 cchar 유형 의 변수는 변수를 성공적으로 보유 할 수 있습니다.

왜 이것이 작동합니까? 위에서 언급 한 책의 설명에 따라 코드가 작동하지 않아야합니다.



5
값이있는 문자를 읽으면이 코드가 실패 할 수 있습니다 0xff. 결과 저장 getchar()에서 int해결할 수있는 문제 그 문제를. 귀하의 질문은 comp.lang.c FAQ의 질문 12.1과 본질적으로 동일 하며 훌륭한 자료입니다. (또한 main()이어야하며 마감 전에 int main(void)추가하는 것이 아프지 않을 것 입니다.)return 0;}
Keith Thompson

1
@delnan : 유닉스가 control-D를 다루는 방법에 대해서는 링크 된 기사가 옳지 않습니다. 입력 스트림을 닫지 않습니다. 콘솔에서 차단되는 fread ()가 아직 읽지 않은 데이터와 함께 즉시 반환되도록합니다. 많은 프로그램이 EOF를 나타내는 것으로 fread ()에서 0 바이트 리턴을 해석하지만 실제로 파일은 열린 상태로 유지되며 더 많은 입력을 제공 할 수 있습니다.
supercat

답변:


11

암시 적 유형 변환이 실수로 올바른 작업을 수행하기 때문에 코드가 작동하는 것 같습니다.

getchar()int의 범위 unsigned char또는에 맞는 값을 갖는를 반환합니다 EOF(음수 여야 함, 일반적으로 -1). 그 EOF자체는 문자가 아니라 사용 가능한 문자가 더 이상 없다는 신호입니다.

결과에서 보관할 때 getchar()하여 c, 두 가지 가능성이있다. 유형 char은 값을 나타낼 수 있으며,이 경우 값은 c입니다. 또는 유형 이 값을 나타낼 char 수 없습니다 . 이 경우 어떤 일이 발생할지 정의되지 않습니다. 인텔 프로세서는 새로운 유형에 맞지 않는 높은 비트를 잘라내 char지만 (효과적으로 모듈로 256의 값을 줄임) 그에 의존해서는 안됩니다.

다음 단계는와 비교 c하는 것 EOF입니다. 마찬가지로 EOF이며 int, c변환된다 int에 저장된 값을 보존 할뿐만 아니라 c. c의 값을 저장할 수 있으면 EOF비교는 성공하지만 값을 저장할 c없는 경우 EOFtype으로 변환 하는 동안 복구 할 수없는 정보 손실이 있었기 때문에 비교에 실패 합니다 char.

컴파일러가 char형식을 서명하고 EOF작은 값 을 적합 하게 만들기로 선택한 것 같습니다 char. char서명되지 않은 경우 (또는 사용한 경우 unsigned char) unsigned char의 값을 보유 할 수 없으므로 테스트에 실패했을 수 있습니다 EOF.


또한 코드에 두 번째 문제가 있습니다. 으로 EOF캐릭터 자체가 아니라, 당신이에 강제 char유형 인 것으로 잘못 해석됩니다 거기 문자 가능성이있다 EOF이 제대로 처리 될 경우가 정의되어 있지 절반 가능한 문자는.


입력 강요 char범위 외의 값 CHAR_MIN.. CHAR_MAX, 구현 정의 값을 산출 구현 트랩 표현으로 정의, 또는 구현 정의 신호를 상승 비트 패턴을 생성하거나 요구된다 할 것이다. 대부분의 경우 구현은 2의 보수 감소 이외의 작업을 수행하기 위해 많은 추가 작업을 거쳐야합니다. 표준위원회의 사람들이 다른 이유가없는 상황에서 컴파일러가 다른 컴파일러의 행동과 일치하는 행동을 구현하도록 장려해야한다는 생각에
동의한다면

... 나는 그러한 강요가 신뢰할 만하다고 생각합니다 (코드가 의도를 문서화해서는 안된다는 것이 아니라, (signed char)x명확하고 안전하다고 간주되어야합니다 ((unsigned char)x ^ CHAR_MAX+1))-(CHAR_MAX+1).). 오늘날의 표준을 준수하는 다른 동작을 구현하는 컴파일러; 하나의 위험은 표준이 "최적화"에 대한 관심의 행동을 깨뜨 리도록 변경 될 수 있다는 것이다.
supercat

@supercat : 표준은 대상 프로세서에서 자연스럽게 지원하지 않는 동작을 가진 코드를 컴파일러가 생성하지 않도록 작성되었습니다. 정의되지 않은 동작의 대부분은 (표준 작성 당시) 모든 프로세서가 일관되게 동작하지 않기 때문입니다. 컴파일러가 더욱 성숙해지면서 컴파일러 작성자는 정의되지 않은 동작을 활용하여보다 적극적인 최적화를 시작했습니다.
Bart van Ingen Schenau

일반적으로 표준의 의도는 대부분 설명한대로 였지만 표준은 일부 공통 플랫폼의 컴파일러가 느슨한 사양에서 필요한 것보다 더 많은 코드를 생성하도록 요구하기에 충분히 자세하게 설명되어 있습니다. 유형 강제 변환 int i=129; signed char c=i;은 그러한 동작 중 하나입니다. 비교적 적은 수의 프로세서가 -127 ~ +127 범위에있을 때 c동일 하고 2의 보수 감소와는 다른 -128 ~ +127 범위의 값에 i일관된 매핑을 생성 하는 명령어가 i있습니다. ..
supercat

그런 경우에 신호를 일관되게 발생시킬 것입니다. 표준은 구현이 일관된 매핑을 생성하거나 신호를 일관되게 발생시켜야하므로 표준이 2의 보수 감소 이외의 공간을 남겨 두는 유일한 플랫폼은 포화 산술 하드웨어가있는 DSP와 같은 것입니다. Undefined Behavior의 역사적 근거는 하드웨어 플랫폼에만 국한된 문제가 아니라고 말합니다. 오버플로가 매우 일관된 방식으로 작동하는 플랫폼에서도 컴파일러가이를 포착하는 것이 유용 할 수 있습니다.
supercat
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.