typedef... 좀 가르쳐 주십시요~~

chaos4chaos의 이미지

자료구조 책을 보다 의문이 생겨서요~~

typedef struct tag {
    int aa[10];
    int bb;
};

이렇게 선언하면 tag이 typedef 명으로 지정된다고 씌여있거든요.

게다가,

typedef struct tag {
    int aa[10];
    int bb;
} tag;

이렇게 '구조체 택'하고 'typedef 이름'하고 동일하게 지정하면 안된다고 씌여있습니다.

그런데, 책에 나온 대로 다음과 같은 선언을 하니 에러가 납니다.
선언부에서 문법 검사할 때는 이상없이 넘어가는데, tag_ptr 형으로 선언된 데이터의 요소를 참조하면 에러가 나버립니다.

typedef struct tag *tag_ptr;
typedef struct tag {
    int aa;
    int bb;
};

물론,

typedef struct tag *tag_ptr;
typedef struct tag {
    int aa;
    int bb;
} tag_type;

이렇게 하면, 문제가 없습니다만,

무엇이 잘못되었는지... 이유를 좀 가르쳐 주심..... 감사드리겠습니다.
왜 typedef 이름을 생략하면 에러가 날까요??
C 책 첨부터 다시 봐라!! 등의 가르침도 괘안습니다...^^

aqwerf의 이미지

chaos4chaos wrote:
무엇이 잘못되었는지... 이유를 좀 가르쳐 주심..... 감사드리겠습니다.
왜 typedef 이름을 생략하면 에러가 날까요??
C 책 첨부터 다시 봐라!! 등의 가르침도 괘안습니다...^^

책을 다시 한번 확인해 보시기 바랍니다.

typedef struct tag { 
    int aa[10]; 
    int bb; 
};

는 문제가 있는 것 같은데요..

struct tag { 
    int aa; 
    int bb; 
};

이게 구조체를 정의 하는 것이죠. 이를 typedef으로 만들려면 해당 코드 아래에
typedef struct tag tag_type;

처럼 하면 됩니다.

둘을 따로 따로 하기가 귀찮을때 한번에 직접 해버릴 수도 있죠...

typedef struct tag { 
    int aa; 
    int bb; 
} tag_type;

물론 포인터도 마찬가지죠..

typedef struct tag { 
    int aa; 
    int bb; 
} tag_type, *tag_ptr;
lsj0713의 이미지

typedef는 맨 앞에 typedef가 들어간다는 점을 빼면 변수 선언과 비슷합니다.

int aaa;    // int형 변수 aaa를 선언합니다.
typedef int aaa;    // int란 타입을 aaa란 이름으로 다시 정의합니다.

struct aaa { int a; char b; } NS;    // aaa형 구조체 객체 NS를 선언합니다.
typedef struct aaa { int a; char b; } NS;    // aaa 구조체형을 NS란 이름으로 다시 정의합니다.

따라서 절대로 맨 마지막의 이름을 빠트릴 수 없습니다.

구조체 선언과 재정의를 한꺼번에 할 때는 태그 이름을 빼도 됩니다.

typedef struct { int a; char b; } NS;

단 구조체 안에 자기참조포인터(혹은 그밖에 구조체 자신을 참조하는 데이터형)를 포함할 경우에는 태그 이름을 절대 빠트릴 수 없습니다. 생각해보면 너무도 당연한 거지요;;

typedef struct t_NS { int a; char b; struct _NS *ptr; } NS;

그리고 C에서는 '구조체 택'하고 'typedef 이름'하고 동일하게 지정해도 됩니다. 구조체 태그 이름하고 typedef 이름하고는 다른 이름공간(namespace)을 사용합니다.

typedef struct NS { int a; char b; struct NS *ptr; } NS;

단 C++에서는 두가지가 같은 이름공간을 사용하기 때문에 안됩니다. 사실 struct 로 선언해도 일반적인 타입 이름처럼 쓸 수 있기 때문에 바로 위와 같은 방식으로 쓸 필요도 없습니다.

chaos4chaos의 이미지

너무 감사드립니다.
근 한 오십년 썩은 대장 속의 때가 씼겨나가는 듯 합니다.
시장의 우상이랄까..
유명한 책이라는 이유로 너무 오래 망설였었습니다.

혹시 자료구조 책중에 그 유명한 호로위쯔 책(C 버전)으로 공부하실때,
이런 문제 접하신적이 없는지 궁금합니다.

그 책에서는 분명.. 모든 자료구조의 선언에

typedef struct node *node_ptr;
typedef struct node {
    int aa;
    ele item;
};

등의 형식을 사용하고 있습니다.
물론, 궁금했던것은 어떤 책에서도 위와 같이 사용하는 것을 본적이 없었었다는... 그냥 일반적으로 사용하는 typedef 형식으로 바꾸어 사용했었는데요...
쩝... 호로위쯔 책을 자세히 볼 일이 있어서, 한참을 쳐다릿?,,,, 저렇게 써놓은 이유까지 자세히 나와 있는거 아닙니까!!!!
흠......

확실히,

typedef struct node *node_ptr;
typedef struct node {
    int aa;
    ele item;
} node;

로 바뀌어야 옳다는 확신이 들었지만서도,
너무 유명한 책이다 보니, 그리고, 잘못이라하기에는 너무 기초적인 부분이다보니
쩝... 이럴땐, 제가 뭔가 생각이 얕은 부분을 또 의심해 보게됩니다..

답변 너무 감사드립니다.
어제 밤에 표준 문서랑, 전웅님 책을 붙들고 낑낑 대다가, 머리속이 복잡해져서 대충 이해하고 넘어갔는데, 깔끔하게 정리해 주시니... 이제야 명확히 이해가 되는것 가쓰미다.....
박을 벌려서 스탬프로 찍어주는 듯한 효과가....^^;

chaos4chaos의 이미지

에궁.. 다시 의심이..... :D
horowitz, shani의 자료구조 책 "fundamentals of data structures"에서 사용하는 typedef의 선언 유형이 틀리긴 틀린 건가요?

typedef struct list_node *list_ptr;
typedef struct list_node {
    int data[4];
    list_ptr link;
};

즉, 위 예제에서는 typedef tag를 생략해 버렸습니다.
아직까지 typedef의 정의에서 typedef tag(or alias)를 생략할 수 있다는 문서를 못 봤는데요....(단 한번도)
아무래도, 지원하는 컴파일러나 무슨 근거가 있으니까 저 유명한 책에서
그렇게 쓴게 아닐까요?
게다가 국내 교수님들 강의노트 봐도 전부 똑같이 정의해서 사용하던데요.

저는 아래와 같이 이해하고 있었는데요, 웬지 아닌것 같습니다.

1. typedef와 struct의 이름 공간은 서로 달라서 동일 이름을 쓸 수 있다(C의 경우, C++은 안됨).
2. typedef tag은 절대 생략 못한다.

저자도 테스트해서 이상없었다고, 서문에 써놓고 있는 걸로 봐서는
위와 같은 정의 형태를 지원하는 컴파일러나 관련 문서가 있을 듯 한데....
좀 가르쳐 주시면 감사하겠습니다.
gcc에서는 이것 저것 옵션을 변경해봐도 컴파일에서 항상 실패합니다.

정말이지 typedef의 tag이 생략가능한 경우가 있는지 없는지...
진짜로, 엄청나게, 살벌하게 궁금합니다.

doldori의 이미지

typedef 식별자를 생략하는 것이 가능한지는 모르겠습니다. 호기심에 여러
컴파일러로 시험해 봤는데 gcc, .NET, comeau 전부 컴파일은 되던데요.
경고 레벨에 따라 경고를 줄 때도 있는데 typedef 식별자가 없으면 typedef
키워드를 무시하는 것 같습니다. 지금까지 본 적도 없고 앞으로도 쓸 이유가
없는 코드라서 그렇게 신경을 쓸 이유는 별로 없어 보입니다.
저는 생략이 가능한지 여부보다 저자가 써놓았다는 이유가 궁금하네요.
진짜로, 엄청나게, 살벌하게 궁금합니다. :)

익명 사용자의 이미지

이유는 안봐도 뻔할듯 하네요...
list_node 멤버중 list_ptr은 반드시 pre define 되어야 한다는 정도겠죠?

cinsk의 이미지

chaos4chaos wrote:
에궁.. 다시 의심이..... :D
horowitz, shani의 자료구조 책 "fundamentals of data structures"에서 사용하는 typedef의 선언 유형이 틀리긴 틀린 건가요?

틀렸습니다.
그 책은 원래 Pascal인가? 암튼 다른 언어로 된 DS 책인데, 그것을 C로 바꿔서 재판하고, 또 C++로도 바꿔서 재판을 했는데, 대부분 컴파일만 되는 수준이며, DS적으로는 몰라도 언어를 사용하는 측면에서는 스타일이 나쁜 코드들이 종종 보입니다.

typedef name은 생략할 수 없습니다. 생략할 수 있다면, typedef의 의미가 사라져 버립니다. 결국 의미가 없는 문장이 되어 버립니다.

대신 structure를 선언할 때 쓰는 structure tag name (보통은 그냥 tag라고 부릅니다)은 생략할 수 있습니다. 예를 들면
typedef struct { ... } XXX;
의 꼴이 됩니다.

> 아무래도, 지원하는 컴파일러나 무슨 근거가 있으니까 저 유명한 책에
> 서 그렇게 쓴게 아닐까요?

>게다가 국내 교수님들 강의노트 봐도 전부 똑같이 정의해서 사용하던데요.
잘못된 것이 맞습니다.

저는 아래와 같이 이해하고 있었는데요, 웬지 아닌것 같습니다.

> 1. typedef와 struct의 이름 공간은 서로 달라서 동일 이름을 쓸 수 있다(C의 경우, C++은 안됨).
typedef name은 일반 identifier와 같은 namespace를 사용합니다.
tag name (struct, union, enum)은 또 다른 namespace를 사용합니다.
(각각 따로 namespace가 있는 것은 아니고, 세 가지 모두 하나의 namespace를 씁니다.)

> 2. typedef tag은 절대 생략 못한다.
맞습니다. typedef는 typedef name으로 쓰기 위한 새 identifier를 정의하는 데 쓰는 것이므로, 새 identifier를 소개하지 못하는 typedef 문장은 틀린 것이 됩니다. 참고로, ISO C 표준에 보면 다음과 같이 정의되어 있습니다:

Quote:

6.7.7.3 In a declaration whose storage-class specifier is typedef, each declarator defines an identifier to be a typedef name that denotes the type specified for the identifier ...
cinsk의 이미지

추가하면 C++에서는 typedef가 기존에 존재하는 type name에 대한 alias (다른 이름)를 만들기 위해 사용합니다 (C에서와 비슷함.)

typedef struct aa AA;

문법상, 위 코드에서 "aa"는 C 언어에서 tag라고 부르지만, C++에서는 struct이 class와 같은 개념이기 때문에 class name이라고 합니다.

그리고 C++에서는 같은 scope 내에서 typedef가 다른 타입을 나타내는 이름을 다시 redefine할 수 없게 되어 있습니다 (ISO C++ 표준 7.1.3)

class complex { /* ... */ };
typedef int complex;                             // error: redefinition
죠커의 이미지

cinsk님과 같은 생각입니다.

Quote:
이렇게 '구조체 택'하고 'typedef 이름'하고 동일하게 지정하면 안된다고 씌여있습니다

이 부분부터 다 틀렸죠. "C++"으로 쓰여진 자료구조 책이라면 typedef를 쓰지 않았을 테고 "C"에서는 중복해도 문제가 될 부분이 없습니다.

typedef 의 이름이 생략해서 의미를 가진다는 것은 int a; 형식에서 이름을 생략해서 int; 로 쓰는 것도 의미를 가져야 합니다.

kyang2의 이미지

갑자기 든 생각인데.. 아주 오래된 책이라면..

그 당시 c compiler는 typedef를 저런식으로 선언해도 에러가 나지않았던게 아닐까요??

신이 있다고 가정하지 않는 한, 삶의 목적에 대한 질문은 무의미하다. -B. 러셀, 철학자

chaos4chaos의 이미지

CN wrote:
cinsk님과 같은 생각입니다.

Quote:
이렇게 '구조체 택'하고 'typedef 이름'하고 동일하게 지정하면 안된다고 씌여있습니다

이 부분부터 다 틀렸죠. "C++"으로 쓰여진 자료구조 책이라면 typedef를 쓰지 않았을 테고 "C"에서는 중복해도 문제가 될 부분이 없습니다.

그렇습니다. 이 부분부터 책에 나온 내용입니다. :roll:
typedef tag이 생략 가능하다는, 그리고 struct tag하고 이름이 같으면 안된다는...쩝
이젠 진짜 이해됩니다. 유명한 책이 그것도 책에서 수백번 등장하는 예제와 문장이 설마 틀렸을까하는 생각에 주저주저했지만, 덕분에 광명을 찾았습니다.

그리고, 이 틀린 내용을 가지고 국내 교수님들은 재탕 삼탕에 번역까지 그대로 하신 듯 합니다.
(물론 역자이신 이 석호 교수님은 대단히 존경하긴 합니다만... 쩝)
뭐 typedef 선언이 그리 중요하겠냐 하시면 드릴 말씀없지만,
C를 이용한 자료구조 책이나 강의노트에서 typedef는 설명을 위한 첫 걸음 아닌가요? 그래서 쪼금 집착했었나 봅니다.
그리고, 이 책의 소스를 기준으로 만들고 작성중인 코드가 있어서 나름대로는 상당히 심각했답니다. :)
여튼 무작시럽게 감사드립니다. 진짜 장 청소한 기분입니다.

chaos4chaos의 이미지

kyang2 wrote:
갑자기 든 생각인데.. 아주 오래된 책이라면..

그 당시 c compiler는 typedef를 저런식으로 선언해도 에러가 나지않았던게 아닐까요??

그렇습니다. 이것도 대단히 궁금합니다. :shock:

댓글 달기

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