構造体定義は.hまたは.cファイルに入れるべきですか?


102

structヘッダーのsの完全な定義と単なる宣言の両方を見てきました。1つのメソッドに他のメソッドよりも利点はありますか?

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

typedef struct s s_t;

編集する

明確にするために、オプションは、ヘッダーファイルでの宣言とクラスでの定義、またはヘッダーファイルでの宣言と定義の両方です。どちらを使用しても、どちらかが同じユーザビリティになるはずです。1つがリンケージによるものであっても、そうではありませんか。


私は、例えば、多くのほとんどの重複を見ていないここが、何の完全一致。この点で間違っている場合は修正してください。


2
不透明または不透明でない構造体が必要ですか?

4
補足として、識別子_tはPOSIXによって予約されているため、通常これはお勧めできません。あなたはただすることができますtypedef struct toto toto
Jens Gustedt、2011年

_t他の場所(たとえば、lighttp、linux)をたくさん使用しているのを見てきました...そして、projident_を前に付けますので、問題にならないはずです。
アーロンYodaiken

そして、@ WTPは、不透明ではCない方が一般に優れていると考えられており、より洗練されていると思います(FILE例については)。したがって、不透明ではありません。
アーロンYodaiken

不透明でない構造体の場合は、ヘッダーファイルに入れる必要があります。そうでない場合、コードはDRYではありません(繰り返してはいけません)。

回答:


107

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

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


4
私はこの答えにもっと同意すると思います。それは、他の.cファイルを通じて構造体を使用するかどうかではなく、構造体をパブリック(つまり、アクセス可能)と見なすべきかどうかです。
c00kiemon5ter

@τεκあなたが意味するかgloballocal可視性?public構造体では意味がありません。すべての構造体はデフォルトでパブリックです。
BugShotGG 2015

3
@Geo PapasこれはCに関する質問です。C publicはC のキーワードではありません。以下のMatthew Slatteryの回答を見ると、ヘッダーで前方宣言のみを使用すると、ユーザーがメンバーのメンバーを使用しようとするとコンパイラエラーが発生することがわかります。プライベート(不透明)構造体。
τεκ

68

どちらを使用しても、どちらかが同じユーザビリティになるはずです。1つがリンケージによるものであっても、そうではありませんか。

いいえ、同じヘッダーを含む他の.cファイルを検討するときは違います。構造体の定義がコンパイラーから見えない場合、その定義の詳細は使用できません。定義のない宣言(例:だけ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;
}

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

$ 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

そのような例をありがとう!dereferencing pointer to incomplete typeまさに私のケースでした!
Timur Fayzrakhmanov

私だけのようにすべてのパブリックにアクセス可能ではない構造体が不良であることを追加することになります。あなたは、インスタンスのデータを記入し、それを送信するためにあなたのAPIのユーザーを有効にすることもできます
アレクサンダーTorstling

@ Mahesha999、そこには魔法はありません。SOは、ゴミを入れてもコードを強調表示します。投稿の後半でコマンドライン出力を強調表示しようとしていることに注意してください。
ウィンガーセンドン2018年

8

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

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


3

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

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



-4

一般に、ヘッダーファイルとソースファイルのどちらに配置しても大きな違いはないと思います。ただし、複数のソースファイルから構造体のメンバーにアクセスする必要がある場合は、構造体をヘッダーファイルに入れて、構造体が必要な他のファイルから含める方が簡単です。


8
-1:優れたソフトウェアエンジニアリング(抽象化、モジュール性など)に関心がある場合は、構造体の定義をどこに置くかが実際に重要です
Paul R
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.