[완료]fgetc 를 char형 변수에 넣어도 상관없나요?

dcmru의 이미지

fgetc 를 man 페이지를 찾아보면

int fgetc(FILE *stream);

이렇게 나옵니다.

제목처럼 char형 변수를 하나 선언해서 fgetc로 받은 값을 넣어도 상관이없나요?

상관이 있다면, int형 변수에 값을 받고, 받은 int형 변수를 강제형변환시켜

char형 변수에 대입을 하는 방법은 문제가 있을 소지가 있나요?

위의 글을 코드로 표현하면,

char ch;
FILE *in;

in=fopen("test", "w");

ch = fgetc(in);

입니다. 문제가 있다면,

이것을 int형 변수 하나를 선언해서,

int ich;

ich = fgetc(in);
ch = (char)ich;

하는 방법은 어떤가요?

왜 이런 질문을 올리게 되었냐면, AIX에서, while 조건문에서 char형 변수와 EOF가 비교가 되지 않는군요.

EOF가 -1로 define 되어있습니다.

IsExist의 이미지

둘다 가능하지만 두번째 방법을 사용하면 type conversion에 대한 경고 메시지를
없앨수 있습니다.
---------
간디가 말한 우리를 파괴시키는 7가지 요소

첫째, 노동 없는 부(富)/둘째, 양심 없는 쾌락
셋째, 인격 없는 지! 식/넷째, 윤리 없는 비지니스

이익추구를 위해서라면..

다섯째, 인성(人性)없는 과학
여섯째, 희생 없는 종교/일곱째, 신념 없는 정치

---------
간디가 말한 우리를 파괴시키는 7가지 요소

첫째, 노동 없는 부(富)/둘째, 양심 없는 쾌락
셋째, 인격 없는 지! 식/넷째, 윤리 없는 비지니스

이익추구를 위해서라면..

다섯째, 인성(人性)없는 과학
여섯째, 희생 없는 종교/일곱째, 신념 없는 정치

익명사용자의 이미지

전웅의 이미지

위에 인용된 C FAQs 에서 확인할 수 있듯이 컴파일러가 경고를 주든
그렇지 않든 문제가 있는 구조입니다 - C FAQs 가 상황을 설명하는 방식
에는 너무 간단히 다루느라 다소 오류가 있습니다만 결론은 맞다고 볼 수
있습니다.

보다 쉽게 생각해보면, fgetc 함수는 unsigned char 형으로 표현되는
문자와 더불어 음수값으로 표현되는 EOF 를 반환할 수 있습니다.

char 형이 signed char 형과 동등한 표현 범위를 갖는 경우 (CHAR_MIN ==
SCHAR_MIN && CHAR_MAX == SCHAR_MAX), char 는 음수를 표현할 수 있기에
EOF 를 올바르게 표현할 수 있으나 SCHAR_MAX < UCHAR_MAX 이기에
unsigned char 로 표현할 수 있는 문자 중 일부를 고유하게 표현할 방법
이 없습니다.

char 형이 unsigned char 형과 동등한 표현 범위를 갖는 경우 (CHAR_MIN
== 0 && CHAR_MAX == UCHAR_MAX), char 가 음수로 표현되는 EOF 를
올바르게 (적법한 문자와 구분되게) 표현할 수 없습니다.

즉, fgetc 가 반환할 수 있는 값의 종류가 char 형이 고유하게 표현할 수
있는 값의 종류보다 많기 때문에 늘 문제가 발생하게 됩니다.

결론은, 표준 입출력 함수에서 문자와 더불어 EOF 가 관련되어 있다면
반드시 int 형을 사용하시기 바랍니다.

* signed char, unsigned char, int 형 및 EOF 의 값과 관련된 보다
복잡한 문제가 남아 있긴 하지만, DSP 같은 특수한 환경이 아니고서는
발생하지 않는 문제이므로 고민할 필요는 없어 보입니다.

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

dcmru의 이미지

궁금증이 풀렸습니다. 사소해 보이는 것이라도 고민을 해봐야할 문제이군요.

제가 쓸려는 형태는

int ich;

while((ich = fgetc(in)) != EOF) {
ch = (char)ich;
...
}

입니다.

일단 fgetc에서는 ich로 값을 입력 받았으므로, EOF처리는 했습니다.

그렇다면 ch = (char)ich; 는 문제의 소지가 있는지요?

혹시 fgetc가 반환할 수 있는 값의 범위를 알 수 있는지요?

노력만이 살길이다.

노력만이 살길이다.

전웅의 이미지

이미 제 답변에 나와 있는 내용입니다.

fgetc 에서 EOF 를 배제하고 나면, 남는 값의 범위는 unsigned char 가
표현할 수 있는 값의 범위입니다 (0 ~ UCHAR_MAX).

"보통은" char 가 signed char 와 동일한 표현 범위를 갖는 경우에도
u-char 의 값을 char 로 변환할 때 u-char 의 모든 값을 고유하게 표현할
수 있습니다.

불행히도 "이론적으로는" 그렇지 못합니다 (예를 들어, char 가 signed 일
때, char 가 표현할 수 없는 u-char 의 값을 char 로 변환한 결과는 구현체
의존적입니다, 또한 일반적인 환경에서는 좀처럼 보기 어려운 signed zero
문제도 있을 수 있습니다).

때문에 문자를 다룰 때 표준에 입각한 full portability 를 고민하시면
코드가 심하게 복잡해 집니다. 대신, fgetc 로 입력받은 것이 진짜로
"문자"라면 char 를, 임의의 "바이트 값"이라면 u-char 를 사용한다는 것을
현실적인 기준으로 삼으시면 충분하리라 생각합니다.

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.