C언어, 호환되는 데이터형 어떻게 구별할수 있는가요?

gurumong의 이미지

공부를 하다보니 호환되는 데이터형인지 아닌지 구별해야할 경우가 있을꺼 같은데요

C언어에서 호환되는 데이터형을 어떻게 구별할수 있을까요?

굉장히 쉬운 질문이긴 한데 웹서칭으로 도저히 찾을수가 없어서 T.T

전웅의 이미지

> 공부를 하다보니 호환되는 데이터형인지 아닌지 구별해야할 경우가 있을꺼 같은데요
>
> C언어에서 호환되는 데이터형을 어떻게 구별할수 있을까요?
>
> 굉장히 쉬운 질문이긴 한데 웹서칭으로 도저히 찾을수가 없어서 T.T
>

type 을 올바르게 이해하지 못한 상황에선 쉬운 문제가 아닙니다.

일단, 서로 "같은" type 이면 호환되는 type 입니다. 여기에 추가로 서로
같지 않아도 충분히 비슷한 경우 추가로 호환되는 type 이 되는 경우가
있습니다 - 따라서 앞 문장의 역은 참이 아닙니다. 예를 들어, 크기를
명시하지 않은 배열과 명시된 배열은 요소 type 이 같으면 (서로 다른
type 이지만) 호환되는 type 입니다. 이런 추가적인 규칙은 책에서도 잘
다루고 있을 겁니다.

서로 다른데 호환되는 type 이 되는 경우가 많지 않기 때문에, 일단 완전히
같은 type 인지 살피고, 그렇지 않은 경우 서로 다른 type 이 호환될 수
있는 경우에 해당하는지 판단하면 간단히 호환 type 여부를 확인할 수
있습니다. 물론 type 에 대해 올바르게 이해하고 있을 때 가능한 이야기
입니다.

호환 type 을 100% 정확히 알려주는 툴은 따로 없습니다. 사람이 보는
type 이 컴파일러가 보는 type 보다 추상적이기 때문에, 반드시 사람의
올바른 판단이 우선하고 이를 보조하는 수단으로만 컴파일러가 사용되어야
합니다.

보조적 수단으로 컴파일러를 사용하고자 한다면, 상황에 따라 여러 방법이
있을 수 있겠지만 가장 일반적으로 사용할 수 있는 방법으로는 대입 연산자
가 있습니다.

대입 연산자에서 양쪽 피연산자가 포인터인 경우, "기본적으로" 두
포인터가 가리키는 type 이 호환되어야 합니다. 이와 같은 규칙은
"constraint" 로 주어져 있으며, constraint 는 프로그램이 지키지 못할
경우 표준을 따르는 컴파일러는 반드시 진단 메시지(경고나 오류 메시지)를
출력하도록 요구하고 있습니다.

따라서 A 라는 type 과 B 라는 type 이 호환되는지 확인하고자 한다면
pointer to pointer to A 와 pointer to pointer to B 를 만들어 하나를
다른 하나에 대입해 보며 컴파일 결과를 확인해 볼 수 있습니다. (왜
pointer to ... 가 아닌 pointer to pointer to ... 를 해야 하는지는 아래
에서 설명합니다.)

예를 들어, char 가 signed char 와 동일한 표현 범위(SCHAR_MIN ~
SCHAR_MAX)를 가질 때 char 가 type algebra 에서도 signed char 와 "호환"
될 수 있는 type 인지 확인하고자 한다면,

int main(void)
{
   char **ppc;
   signed char **pps;
 
   (void) sizeof(ppc = pps);   /* valid or invalid? */
}

과 같은 간단한 코드가 표준 모드(gcc 의 경우 -ansi -pedantic)에서 아무
진단 메시지 없이 번역되는지 확인해 볼 수 있습니다. (sizeof 를 쓴 이유
는 수식 p2 = p1 이 실제 수행되는 것을 막기 위한 것입니다.)

확인하고자 하는 type 의 포인터를 한번이 아닌 두번 취하는 이유는, 대입
연산자가 호환되지 않는 경우에도 대입을 허용하고 있는 경우를 가능한
피하기 위해서입니다. 예를 들면,

- void 와 int 는 당연히 호환되지 않는 type 입니다. 만약, 위에서
말씀드린대로 포인터를 2번 취하지 않고 한번만 취해 대입 연산자로
시험해보면 어떤 결과가 발생할까요?

void *pv;
int *pi;
 
(void) sizeof(pv = pi);   /* no problem */
(void) sizeof(pi = pv);   /* no problem */

void * 가 대상체 포인터의 일반 포인터(generic pointer)이기에 대상체
포인터 int * 를 대입하거나 그 반대로 int * 를 void * 에 대입하는 것이
특별히 허용되고 맙니다. 이런 경우를 위해 위에서 말씀드린대로 해당 type
(void 와 int) 의 pointer 를 두 번 취해 대입할 경우 아래와 같이 기대한
결과를 확인할 수 있습니다.

void **ppv;
int **ppi;
 
(void) sizeof(ppv = ppi);   /* invalid */
(void) sizeof(ppi = ppv);   /* invalid */

즉, 위에서 설명드린대로 void 와 int 는 당연히 호환되지 않는 type
입니다.

- const int 와 int 는 호환되지 않는 type 입니다. 이 경우에도 포인터를
한번만 취하게 되면 pointer to const int 로 pointer to int 를 대입하는
것이 가능해집니다 (좌측 피연산자로 주어진 포인터가 가리키는 type 이
우측 피연산자로 주어진 포인터가 가리키는 type 보다 "더" 한정되어 있는
경우에는 호환되지 않아도 대입이 허용됩니다).

const int *pci;
int *pi;
 
(void) sizeof(pci = pi);   /* no problem */

하지만, 이 경우에도 포인터를 두번 취하면 호환되지 않는 type 임을
확인할 수 있게 됩니다.

const int **ppci;
int **ppi;
 
(void) sizeof(ppci = ppi);   /* invalid */

마지막으로, C 언어에서 각 열거 type 은 어떤 정수형과 호환되는 type
입니다. 하지만, (몇가지 조건이 만족되기만 하면) 그 호환되는 정수형으로
무엇이 선택될지는 알 수 없기 때문에 사실상 열거 type 과 정수형은 서로
다른 type 으로 가정해야 안전합니다. 하지만, 만약 특정 구현체에서 어떤
열거형과 int 형이 호환되는 type 으로 선택되었다면, 포인터를 두번
취해서 대입을 하더라도 진단이 발생하지 않습니다. 이는 "해당"
구현체에서 두 type 이 실제로 호환이 되기 때문입니다만, 그렇다고 "모든"
구현체에서 둘을 호환되는 type 으로 가정할 수 있다고 의미하는 것은
아닙니다.

이 정도면 주의해야 할 경우는 다 언급한 것 같습니다. 하지만, 이런
실험적인 방법은 어디까지나 호환 type 이해의 보조 수단임을 다시 한번
강조합니다.

--
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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.