c의 여러 파일에서 사용할 헤더의 구조를 선언하는 방법은 무엇입니까?


115

구조체가있는 source.c 파일이있는 경우 :

struct a { 
    int i;
    struct b {
        int j;
    }
};

이 구조체를 다른 파일 (예 :)에서 어떻게 사용할 수 func.c있습니까?

새 헤더 파일을 만들고 거기에 구조체를 선언하고 해당 헤더를 포함해야 func.c합니까?

아니면 내가 헤더 파일에서 전체 구조체를 정의하고 모두 그를 포함해야 source.c하고 func.c? extern두 파일에서 구조체를 어떻게 선언 할 수 있습니까?

그럴까요 typedef? 그렇다면 어떻게?


구조 정의가 유효하지 않다는 점에 유의하십시오. C.에 대한 닫기 중괄호 뒤에 세미콜론이 있어야 struct b하지만 구조에서 a사용되지 않는 유형을 선언합니다 (아마도 k내부 닫기 중괄호 뒤에 멤버 이름을 정의해야합니다. 세미콜론 앞
Jonathan Leffler 2014 년

답변:


140

이 구조가 다른 파일 func.c에서 사용되는 경우 어떻게해야합니까?

유형이 파일 (예 : func.c 파일)에서 사용되는 경우 표시되어야합니다. 가장 나쁜 방법은 필요한 각 소스 파일에 복사하여 붙여 넣는 것입니다.

올바른 방법은 헤더 파일에 넣고 필요할 때마다이 헤더 파일을 포함하는 것입니다.

새 헤더 파일을 열고 거기에 구조를 선언하고 그 헤더를 func.c에 포함시킬까요?

이것은 코드를 고도로 모듈화하기 때문에 내가 더 좋아하는 솔루션입니다. 구조체를 다음과 같이 코딩합니다.

#ifndef SOME_HEADER_GUARD_WITH_UNIQUE_NAME
#define SOME_HEADER_GUARD_WITH_UNIQUE_NAME

struct a
{ 
    int i;
    struct b
    {
        int j;
    }
};

#endif

이 구조를 사용하는 함수를 동일한 헤더 ( "인터페이스"의 "의미 상"부분 인 함수)에 넣습니다.

일반적으로 구조 이름 뒤에 파일 이름을 지정하고 해당 이름을 다시 사용하여 헤더 가드가 정의하는 것을 선택할 수 있습니다.

구조체에 대한 포인터를 사용하여 함수를 선언해야하는 경우 전체 구조체 정의가 필요하지 않습니다. 다음과 같은 간단한 전방 선언 :

struct a ;

충분하고 결합을 감소시킵니다.

또는 헤더 파일에 전체 구조를 정의하고이를 source.c와 func.c 모두에 포함 할 수 있습니까?

이것은 좀 더 쉬우면서도 덜 모듈화 된 또 다른 방법입니다. 구조 만 작동해야하는 일부 코드는 여전히 모든 유형을 포함해야합니다.

C ++에서 이것은 흥미로운 복잡성을 유발할 수 있지만 이것은 주제에서 벗어난 것입니다 (C ++ 태그 없음). 따라서 자세히 설명하지 않겠습니다.

그런 다음 두 파일에서 해당 구조를 extern으로 선언하는 방법. ?

나는 요점을 보지 못했지만 Greg Hewgill은 자신의 게시물에서 How to declare a structure in a header in multiple files in c? .

그럼 어떻게 typedef할까요?

  • C ++를 사용하는 경우에는 사용하지 마십시오.
  • C를 사용하고 있다면 그렇게해야합니다.

그 이유는 C 구조체 관리가 고통 스러울 수 있기 때문입니다. 사용되는 모든 곳에서 구조체 키워드를 선언해야합니다.

struct MyStruct ; /* Forward declaration */

struct MyStruct
{
   /* etc. */
} ;

void doSomething(struct MyStruct * p) /* parameter */
{
   struct MyStruct a ; /* variable */
   /* etc */
}

typedef를 사용하면 struct 키워드없이 작성할 수 있습니다.

struct MyStructTag ; /* Forward declaration */

typedef struct MyStructTag
{
   /* etc. */
} MyStruct ;

void doSomething(MyStruct * p) /* parameter */
{
   MyStruct a ; /* variable */
   /* etc */
}

구조체의 이름을 유지하는 것이 중요 합니다. 쓰기:

typedef struct
{
   /* etc. */
} MyStruct ;

typedef-ed 이름으로 익명 구조체를 생성하고 포워드 선언 할 수 없습니다. 따라서 다음 형식을 유지하십시오.

typedef struct MyStructTag
{
   /* etc. */
} MyStruct ;

따라서 struct 키워드를 추가하지 않으려는 모든 곳에서 MyStruct를 사용할 수 있으며 typedef가 작동하지 않을 때에도 MyStructTag를 사용할 수 있습니다 (예 : 정방향 선언).

편집하다:

Jonathan Leffler가 올바르게 언급 한대로 C99 구조체 선언에 대한 잘못된 가정을 수정 했습니다 .

2018-06-01 수정 :

Craig Barnes 는 자신의 의견에서 명확성을 위해 위에서했던 것처럼 구조체 "태그"이름과 "typedef"이름에 대해 별도의 이름을 유지할 필요가 없음을 상기시킵니다.

실제로 위의 코드는 다음과 같이 작성 될 수 있습니다.

typedef struct MyStruct
{
   /* etc. */
} MyStruct ;

IIRC, 이것은 실제로 C ++이 C와의 호환성을 유지하기 위해 더 간단한 구조체 선언으로 수행하는 작업입니다.

// C++ explicit declaration by the user
struct MyStruct
{
   /* etc. */
} ;
// C++ standard then implicitly adds the following line
typedef MyStruct MyStruct;

C로 돌아가서 두 가지 사용 (별도의 이름과 같은 이름)을 보았지만 내가 아는 단점은 없습니다. 따라서 구조체와 다른 기호에 대해 C 별도의 "네임 스페이스"를 사용하지 않으면 같은 이름을 사용하면 읽기가 더 쉬워집니다. .


2
"C99를 사용하는 경우에는하지 마십시오"라는 의견을 보증하는 C99 표준 섹션에 대해 언급하거나 지적 할 수 있습니까?
Jonathan Leffler

네가 옳아. 최근에 C99를 테스트 한 결과 C ++ 방식을 사용할 때 유형 정의되지 않은 구조체가 인식되지 않는다는 사실에 놀랐습니다. 컴파일러 옵션을 검색 한 후 모든 표준 문서에서 손에 넣을 수는 있었지만 가능하다고 생각하는 설명이없는 것을 발견했습니다 ...
paercebal

2
... 어쨌든, 발언 주셔서 감사합니다. 지금 바로 수정했습니다.
paercebal

struct태그와 이름에 다른 이름을 사용할 필요가 없습니다 typedef. C는 struct태그에 다른 네임 스페이스를 사용 MyStruct하므로 둘 다 사용할 수 있습니다 .
Craig Barnes

1
@CraigBarnes 맞습니다.하지만 코드를 읽는 것만으로도 명확 해지기를 원했습니다. 내가 같은 이름을 주었 더라면 같은 "선언"에 * 두 번 "이라는 이름을 써야 할 필요성에 대해 C 초보자를 혼동 할 수 있습니다. 귀하의 의견을 언급하는 메모를 추가하겠습니다. 감사합니다!
paercebal

34

둘 이상의 소스 파일에서 사용할 구조 정의의 경우 반드시 헤더 파일에 넣어야합니다. 그런 다음 구조가 필요한 소스 파일에 해당 헤더 파일을 포함합니다.

extern선언은 구조 정의를 사용하지 않으며, 대신 (즉, 구조 유형 일부 데이터 값을 사용자가 정의한 것을) 변수 선언에 사용됩니다. 둘 이상의 소스 파일에서 동일한 변수를 사용하려면 다음과 extern같이 헤더 파일에서 선언하십시오 .

extern struct a myAValue;

그런 다음 하나의 소스 파일에서 실제 변수를 정의하십시오.

struct a myAValue;

이 작업을 잊었거나 실수로 두 개의 소스 파일에 정의한 경우 링커가 이에 대해 알려줍니다.


링커 오류가 발생할 수도 있고 아닐 수도 있습니다. C에서 연결 모델은 '공통'정의를 허용하므로 이니셜 라이저가없는 (그리고 동일한 이니셜 라이저를 사용하는) 여러 정의가 작동 할 수 있습니다. '공통 확장'입니다. 일부 컴파일러는 임시 (누락 된) 정의도 지원합니다.
Jonathan Leffler

그런 다음 하나의 소스 파일 에서 실제 변수를 정의 하십시오.; ... 또는 실수 로 두 개의 소스 파일에 정의 ... :)
Johannes Schaub-litb

나는 선언에 사용했습니다 하나 개의 기술 / 문제가 조건부로 정의하는 것입니다 정의 GLOBALextern다음과 같이 변수를 선언하거나 헤더 상단에 아무것도하고 GLOBAL struct a myAValue;. 대부분의 소스 파일에서 #define GLOBAL extern사용할 버전 ( 변수 선언 ) 을 정렬 하고 정확히 하나의 소스 파일에서 빈 정의를 사용하여 변수를 정의 합니다.
TripeHound

C에서 typedef 이름과 동일한 구조 이름을 가질 수 있지만 C ++에서는 사용할 수 없습니다.
xuhdev

6

아 :

#ifndef A_H
#define A_H

struct a { 
    int i;
    struct b {
        int j;
    }
};

#endif

이제이 구조를 사용하려는 파일에 ah를 포함하면됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.