この構造が他のファイル 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 that is to be used by 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 された名前を持つ匿名構造体を作成するだけで、それを前方宣言することはできません。したがって、次の形式を守ってください。
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 の別の「名前空間」を使用しない場合、同じ名前を使用すると読みやすくなります。 .