web-dev-qa-db-ja.com

構造体の定義は.hまたは.cファイルに入れる必要がありますか?

ヘッダーのstructsの完全な定義と単なる宣言の両方を見てきました。1つのメソッドが他のメソッドよりも優れているのでしょうか。

それが違いを生む場合、私は通常.hでそのような構造体をtypedefします

typedef struct s s_t;

編集

明確にするため、オプションはヘッダーファイルでの宣言とクラスでの定義、またはヘッダーファイルでの宣言と定義の両方です。どちらもリンケージによるものであっても、同じ使いやすさになるはずです。


多くの重複が見られます。 ここ しかし、完全に一致するものはありません。この点で間違っている場合は修正してください。

92
Aaron Yodaiken

そのファイルのプライベート構造体は、.hの関数で使用される場合、.hファイルの宣言とともに.cファイルに入れます。

パブリック構造体は.hファイルに入れる必要があります。

94
τεκ

どちらもリンケージによるものであっても、同じ使いやすさになるはずです。

いいえ、同じヘッダーを含む他の.cファイルを検討する場合ではありません。構造体の定義がコンパイラーに表示されない場合、その定義の詳細は使用できません。定義のない宣言(たとえばstruct s;)を使用すると、struct sの内部を調べようとするとコンパイラは失敗しますが、 struct s *foo;をコンパイルします(fooが後で参照解除されない限り)。

api.hapi.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;
}

これは、「ヘッダーの定義」バージョンでは機能しますが、「実装の定義」バージョンでは機能しません。後者の場合、コンパイラーは構造のレイアウトを認識できないためです。

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

したがって、「実装の定義」バージョンは、プライベート実装の詳細の偶発的または意図的な誤用から保護します。

66

構造体を他のコンパイルユニット(.cファイル)で使用する場合は、ヘッダーファイルに配置して、必要に応じてそのヘッダーファイルを含めることができるようにします。

構造体が1つのコンパイル単位(.cファイル)でのみ使用される場合、その.cファイルに配置します。

7
nos

ポイントは、ヘッダーファイルに配置すると、そのヘッダーファイルを含めるだけで、複数のソースファイルの構造(またはその他の定義)を使用できるようになることです。

ただし、1つのソースファイルからのみ使用されると確信している場合は、実際には違いはありません。

3
Jonathan Wood

オブジェクトをよりオブジェクト指向にするために、Cファイルに入れます この記事を参照

0
TofuBeer