構造体を持つsource.cファイルがある場合:
struct a {
int i;
struct b {
int j;
}
};
この構造体を別のファイル(つまりfunc.c
)で使用するにはどうすればよいですか?
新しいヘッダーファイルを作成し、そこで構造体を宣言して、そのヘッダーをfunc.c
に含める必要がありますか?
または、ヘッダーファイルで構造体全体を定義し、source.c
とfunc.c
の両方に含める必要がありますか?両方のファイルでextern
構造体を宣言するにはどうすればよいですか?
typedef
すべきですか?もしそうなら、どのように?
ファイル(つまり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 ;
十分であり、カップリングを減少させます。
これは別の方法で、多少簡単ですが、モジュール性は低くなります。機能するのに構造だけが必要なコードには、すべてのタイプを含める必要があります。
C++では、これは興味深い複雑化につながる可能性がありますが、これはトピック外(C++タグなし)なので、詳しく説明しません。
おそらく、ポイントはわかりませんが、Greg Hewgillの投稿で非常に良い答えがあります cの複数のファイルで使用されるヘッダーの構造を宣言する方法 。
その理由は、C構造体の管理が苦痛になる可能性があることです。使用するすべての場所でstructキーワードを宣言する必要があります。
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 */
}
importantまだ構造体の名前を保持しています。書き込み:
typedef struct
{
/* etc. */
} MyStruct ;
typedefされた名前で匿名の構造体を作成するだけで、前方宣言することはできません。そのため、次の形式に従ってください。
typedef struct MyStructTag
{
/* etc. */
} MyStruct ;
したがって、structキーワードの追加を回避したいすべての場所でMyStructを使用でき、typedefが機能しない場合(つまり前方宣言)でもMyStructTagを使用できます。
Jonathan Leffler で正しく述べられているように、C99構造体宣言に関する誤った仮定を修正しました。
Craig Barnes コメントで、構造体の「タグ」名とその「typedef」名に別々の名前を付ける必要はないことを思い出させてくれます。
実際、上記のコードは次のように書くこともできます。
typedef struct MyStruct
{
/* etc. */
} MyStruct ;
IIRC、これは実際には、C++とCとの互換性を保つために、舞台裏でC++がより単純な構造体宣言で行うことです。
// C++ explicit declaration by the user
struct MyStruct
{
/* etc. */
} ;
// C++ standard then implicitly adds the following line
typedef MyStruct MyStruct;
Cに戻って、両方の使用法(別々の名前と同じ名前)を見てきましたが、どれも私が知っている欠点はないので、同じ名前を使用すると 構造体およびその他の記号 。
複数のソースファイルで使用される構造定義の場合は、必ずヘッダーファイルに配置する必要があります。次に、そのヘッダーファイルを、構造が必要なソースファイルに含めます。
extern
宣言は構造定義には使用されませんが、代わりに変数宣言(つまり、定義した構造タイプを持つ一部のデータ値)に使用されます。同じ変数を複数のソースファイルで使用する場合は、次のようなヘッダーファイルでextern
として宣言します。
extern struct a myAValue;
次に、oneソースファイルで、実際の変数を定義します。
struct a myAValue;
これを行うのを忘れた場合、または誤って2つのソースファイルで定義した場合、リンカーはこれを通知します。
a.h:
#ifndef A_H
#define A_H
struct a {
int i;
struct b {
int j;
}
};
#endif
これで、この構造を使用するファイルにa.hを含めるだけです。