구조체 정의는 .h 또는 .c 파일에 있어야합니까?


102

struct헤더에서 s의 전체 정의 와 선언 만 보았습니다. 한 메서드가 다른 메서드에 비해 이점이 있습니까?

차이가 나는 경우 일반적으로 다음과 같은 구조체를 typedef합니다. .h

typedef struct s s_t;

편집하다

명확하게 말하면 옵션은 헤더 파일의 선언과 클래스의 정의 또는 헤더 파일의 선언과 정의입니다. 둘 다 연결에 의한 경우에도 동일한 사용성을 가져야합니다. 그렇지 않습니까?


예를 들어 여기 에는 거의 중복되는 항목이 많이 있지만 정확한 일치 항목은 없습니다. 이 점에서 내가 틀렸다면 나를 바로 잡으십시오.


2
불투명하거나 불투명하지 않은 구조체를 원하십니까?

4
참고로, 식별자가 _t있는 식별자 는 POSIX에 의해 예약되어 있으므로 이는 일반적으로 나쁜 생각입니다. 당신은 할 수 있습니다 typedef struct toto toto.
Jens Gustedt 2011-06-11

_t다른 장소 (예 : lighttp, linux)를 많이 사용하는 것을 보았습니다 ... 그리고 projident_ 접두사를 붙입니다. 그래서 문제가되지 않아야합니까?
Aaron Yodaiken 2011-06-11

그리고 @WTP, 나는 불투명하지 않은 것이 일반적으로 더 좋고 더 많은 것으로 간주된다고 생각합니다 C( FILE예제 등). 그래서 불투명하지 않습니다.
Aaron Yodaiken 2011-06-11

불투명하지 않은 구조체라면 헤더 파일로 들어가거나 코드가 DRY가 아닙니다 (반복하지 마십시오).

답변:


107

해당 파일의 개인 구조는 .c 파일에 있어야하며, .h의 함수에서 사용되는 경우 .h 파일에 선언이 있어야합니다.

공용 구조는 .h 파일에 있어야합니다.


4
이 답변에 더 동의한다고 생각합니다. 다른 .c 파일을 통해 구조체를 사용하는 것이 아니라 구조체를 공용으로 간주해야하는지 (액세스 할 수 있는지) 여부입니다.
c00kiemon5ter 2011-06-11

@ τεκ 의미 globallocal가시성? public구조체에서는 의미가 없습니다. 모든 구조체는 기본적으로 공용입니다.
BugShotGG 2015

3
@Geo Papas 이것은 C에 대한 질문입니다 .C public의 키워드가 아닙니다. 아래 Matthew Slattery의 답변을 보면 헤더에서 정방향 선언 만 사용하면 사용자가 a의 멤버를 사용하려고 할 때 컴파일러 오류가 발생하는 방법을 알 수 있습니다. 개인 (불투명) 구조체.
τεκ

68

둘 다 연결에 의한 경우에도 동일한 사용성을 가져야합니다. 그렇지 않습니까?

아니요, 동일한 헤더를 포함하는 다른 .c 파일을 고려할 때는 아닙니다. 구조 정의가 컴파일러에 표시되지 않는 경우 해당 정의의 세부 정보를 사용할 수 없습니다. 정의가없는 선언 (예 : just struct s;)은 내부를 들여다 보려고하면 컴파일러가 실패 struct s하게하고, 예를 들어 struct s *foo;( foo나중에 역 참조되지 않는 한) 여전히 컴파일을 허용합니다 .

api.h및의 다음 버전을 비교하십시오 api.c.

Definition in header:                 Definition in implementation:
+---------------------------------+   +---------------------------------+
| struct s {                      |   | struct s;                       |
|     int internal;               |   |                                 |
|     int other_stuff;            |   | extern void                     |
| };                              |   | api_func(struct s *foo, int x); |
|                                 |   +---------------------------------+
| extern void                     |   +---------------------------------+
| api_func(struct s *foo, int x); |   | #include "api.h"                |
+---------------------------------+   |                                 |
+---------------------------------+   | struct s {                      |
| #include "api.h"                |   |     int internal;               |
|                                 |   |     int other_stuff;            |
| void                            |   | };                              |
| api_func(struct s *foo, int x)  |   |                                 |
| {                               |   | void                            |
|     foo->internal = x;          |   | api_func(struct s *foo, int x)  |
| }                               |   | {                               |
+---------------------------------+   |     foo->internal = x;          |
                                      | }                               |
                                      +---------------------------------+

이 API 클라이언트는 다음 버전 중 하나에서 작동합니다.

#include "api.h"

void good(struct s *foo)
{
    api_func(foo, 123);
}

이것은 구현 세부 사항을 찌릅니다.

#include "api.h"

void bad(struct s *foo)
{
    foo->internal = 123;
}

"definition in header"버전에서는 작동하지만 "definition in implementation"버전에서는 작동하지 않습니다. 후자의 경우 컴파일러는 구조의 레이아웃을 볼 수 없습니다.

$ gcc -Wall -c bad.c
bad.c: In function 'bad':
bad.c:5: error: dereferencing pointer to incomplete type
$

따라서 "구현시 정의"버전은 개인 구현 세부 정보의 우발적 또는 고의적 오용으로부터 보호합니다.


3
코드 창을 어떻게 만들 었는지 알고 싶고 내부에 코드가 강조 표시되어 있는지 ... 수동으로? 이 OP는 stackoverflow를 사용하여 떠난 것 같습니다. '(다른 사람이 말해 줄 수 있습니까? ...
Mahesha999

좋은 예! 감사!
Victor Haine 2016-04-02

그런 예에 감사드립니다! dereferencing pointer to incomplete type정확히 제 경우였습니다!
Timur Fayzrakhmanov

난 그냥 싶다고을 추가하려면 모든 공개적으로 액세스 할 수있는 구조체는 나쁜 : 당신은 예를 들어 데이터를 입력하기 위해 API의 사용을 활성화하고 그것을 보낼 수 있습니다.
알렉산더 Torstling을

@ Mahesha999, 거기에는 마법이 없습니다. 그래서 쓰레기를 넣더라도 코드를 강조합니다. 게시물의 뒷부분에서 명령 줄 출력을 강조 표시하려고합니다.
Winger Sendon

8

구조체가 다른 컴파일 단위 (.c 파일)에서 사용되는 경우 헤더 파일에 배치하여 필요할 때마다 해당 헤더 파일을 포함 할 수 있습니다.

구조체가 하나의 컴파일 단위 (.c 파일)에서만 사용되는 경우 해당 .c 파일에 배치합니다.


3

요점은 헤더 파일에 배치하면 해당 헤더 파일을 포함하는 것만으로 여러 소스 파일의 구조 (또는 다른 정의)를 사용할 수 있다는 것입니다.

그러나 하나의 소스 파일에서만 사용된다는 것이 확실하다면 실제로는 아무런 차이가 없습니다.



-4

일반적으로 헤더 파일에 넣든 소스 파일에 넣든 큰 차이가 없다고 생각합니다. 그러나 여러 소스 파일에서 구조의 멤버에 액세스해야하는 경우 구조를 헤더 파일에 넣고 구조가 필요한 다른 파일에서 포함하는 것이 더 쉽습니다.


8
-1 : 좋은 소프트웨어 엔지니어링 (추상화, 모듈화 등)에 관심이 있다면 실제로 구조체 정의를 어디에 두는 것이 중요합니다
Paul R
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.