구조체에 대해서 질문드립니다.

thslrtoo의 이미지

공부를 하던 도중 책에 이런 구조체 문구가 나오더군요.

typdef struct aaa
{
    ...
    struct bbb *pB;
}AAA, *PAAA;
 
typedef struct bbb
{
    ...
    PAAA pA;
}BBB, *PBBB;

bbb 구조체를 보면 aaa 구조체의 포인터를 멤버로 가지고 있습니다.
bbb 구조체 위에 aaa 구조체 정의가 있으니까 문제가 없겠죠??
근데 제가 궁그한건 aaa 구조체의 pB 멤버입니다.

aaa 구조체가 정의될때는 bbb 구조체를 전혀 모르고있습니다.
물론 포인터형이라서 4Byte 만 할당해주면 되겠지만,
struct bbb 라는 이름 자체를 모르는데 어떻게 저게 가능한지 궁금하네요.

그리고 추가로

PAAA a1; // a1 에 값이 대입되었다고 가정합니다.
PBBB b1 = a1->pB;

위 코드에서 b1 = a1->pB 구문은 책에서는 된다고 나와있습니다.
근데 제가 컴파일 해봤을때는 캐스팅(struct bbb *) 을 하지 않고는 컴파일이 되지 않았습니다.
책이 잘못된건가요??

klara의 이미지

실제로 컴파일 해본 소스코드를 올려주세요.

thslrtoo의 이미지

아.. 소스를 그냥 올려드리는게 빠르겠군요..^^;;
여기 이 소스입니다.

댓글 첨부 파일: 
첨부파일 크기
Package icon Graph.zip921바이트
익명 사용자의 이미지

구조체와 공용체, 배열은 불완전 선언이 가능합니다.
자세한건 incomplete types로 검색해 보시길 권하며..
구조체에 대한 포인터 같은 경우에는 구조체 내부 구조에 대한 정보가 따로 필요가 없으므로,
불완전한 타입만으로도 그에 대해 포인터를 선언할 수가 있습니다.

위의 경우에는 구조체 aaa 선전 부분의 struct bbb *pB; 부분이
구조체 bbb에 대한 불완전 선언으로 작용합니다.
물론, 선언일 뿐이므로 실제로 해당 객체에 접근하기 위해서는
그 뒤에 불완전한 부분에 대해 제대로 정의를 추가적으로 해 줘야 합니다.

그리고 아래 문제에 대해선, 대입 자체는 되는게 맞습니다.
동일한 타입인데 대입이 안되면 이상한 거지요.
다만 좀 맘에 걸리는건 a1이라는 객체 자체가 존재하지 않는다는 점인데...
정렬제한 문제가 있을 수 있겠군요.
일단 에러 메시지의 내용을 확인해 보시길 권합니다.

그리고 컴파일 에러 질문할땐 제발 에러 메시지좀 같이 올리십시오.

익명 사용자의 이미지

다만 좀 맘에 걸리는건 a1이라는 객체 자체가 존재하지 않는다는 점인데...
-> 'a1이 가리키는 객체가'로 바꿔서 읽어주세요.

thslrtoo의 이미지

죄송합니다. 아무 생각없이 질문만 해버렸네요..^^;;
소스코드는 길어서 파일로 첨부하였고 (위 답변에..) 에러 코드는 아래과 같이 뜹니다.

$ g++ -c Graph.cpp 
Graph.cpp: In destructor ‘CGraph::~CGraph()’:
Graph.cpp:22:20: error: cannot convert ‘tagEdge*’ to ‘CGraph::EDGE* {aka CGraph::tagEdge*}’ in assignment

일단 말씀해주신 incomplete type 을 한번 찾아봐야겠습니다. ^^

익명 사용자의 이미지

뭔가 원질문의 예와 Graph.cpp의 예는 다른 상황으로 보입니다.
Graph.cpp의 축약된 버전으로 같은 에러를 보이는 예제를 올려보세요. 그게 어렵다면 압축, 또는 다른 사이트 링크(클라우드 링트 등)으로 올려 보세요. 도움받기 수월할 겁니다.

kaeri17의 이미지

헤더 파일을 다음과 같이 수정하세요

class CGraph
{
private:
    struct tagEdge; //!이게 빠짐.
    typedef struct tagVertex
    {
        int nData;
        int eVisit;
        int nIndex;
        tagVertex *pNext;
        tagEdge *pList;
    }VERTEX, *PVERTEX;
...
익명 사용자의 이미지

질문과 동떨어진 내용인데요..

typedef 가 얼마나 코드 가독성을 헤치는지 이제야 이해가 되네요..

struct aaa
{
...
struct bbb *pb;
};

struct bbb
{
...
struct aaa *pa;
};

이렇게 쉽게 하면 될 것을.. 왜 두세번(혹은 네번 다섯번) 보게 가르켜 주는 걸까요?

익명 사용자의 이미지

질문자가 제시한 상황에서는 typedef 대신 님께서 말한대로 한다고 해도
여전히 같은 문제가 발생합니다.

위 문제는 namespace 혹은 scope와 관련이 있습니다.
class 내부에서 선언된 incomplete type인 구조체가
class 외부에서 정의된 구조체와 서로 별개로 취급되기 때문에 생기는 문제입니다.
즉 tagEdge와 CGraph::tagEdge는 서로 별개의 타입입니다.

typedef를 하지 않았다고 해도 크게 달라지는 문제는 아닙니다.

제가 비슷한 에러 메시지가 나오는 상황을 한번 재현해 봤습니다.

struct CCC
{
	struct BBB { int i; } * pb;
};
 
struct AAA { struct BBB * b; };
 
int main(void)
{
	CCC c1;
	AAA a1;
	c1.pb = a1.b;
 
	return 0;	
}
 
컴파일 에러 :
ex1.cc: In function 'int main()':
ex1.cc:18:13: error: cannot convert 'BBB*' to 'CCC::BBB*' in assignment

그나저나 여기는 비로그인은 로그인이 올린 첨부파일을 볼 수가 없는 모양이군요.

익명 사용자의 이미지

근데 제가 말하고자 한건 typedef 가 가독성을 안 좋게 한다는 대한 내용이지
질문내용에 대한 컴파일 여부는 잘 모르겠네요
선두에 질문과 상관 없지만.. 이라고 적었어요 ㅎㅎ

익명 사용자의 이미지

typedef는 오히려 코드 가독성을 높이는데 유용한 기능입니다.
특히 함수 포인터와 관련해서는, 이거 없으면 굉장히 코드가 끔찍해질 겁니다.

만약 typedef가 코드 가독성을 저해한다면
프로그램의 내부 구조가 이해하기 어렵게 만들어져 있거나
타입 이름이 직관적이지 않아서 그렇겠지요.

익명 사용자의 이미지

예를 한번 들어 볼께요

struct st_device {
RECV_STATE rst;
TRAN_STATE tst;
};

위와 같은 때
RECV_STATE, TRAN_STATE 가 무슨 타입이지?
그래서 찾아 보시겠죠...

struct st_device {
struct recv_st *rst;
struct tran_st *tst;
};

위와 같을 때
rst,tst 가 구조체의 포인터군.. 바로 아실수 있죠?

익명 사용자의 이미지

C++의 struct는 단지 기본 접근자가 public인 class에 불과하기 때문에,
그럴 이유가 전혀 없습니다.

우리가 class의 instance를 선언할때마다 그 옆에 THIS IS CLASS!!!라고 적어주던가요?
마찬가지로, struct도 그럴 필요가 없습니다.

HDNua의 이미지

struct bbb *pB;
[struct bbb] *pB; // [struct bbb] 자체로 전방 선언이지요.

저는 이렇게 생각했습니다.

댓글 달기

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