2009-03-07 13 views
19

私はヘッダファイルport.h、port.c、そして私のmain.cの未定義のC構造体の前方宣言

を持って、私は次のエラーを取得する:「ポートの用途未定義の構造体 'port_t'

I私が自分の.hファイルで構造体を宣言し、.cファイルの実際の構造体を持っていると思ったのは大丈夫でした。

port.cファイルにいくつかのデータを隠したいので、前方宣言が必要です。私port.hで

私は、次のしている:

/* port.h */ 
struct port_t; 

port.c:

/* port.c */ 
#include "port.h" 
struct port_t 
{ 
    unsigned int port_id; 
    char name; 
}; 

のmain.c:任意の提案のための

/* main.c */ 
#include <stdio.h> 
#include "port.h" 

int main(void) 
{ 
struct port_t ports; 

return 0; 
} 

多くのおかげで、

+0

コンパイラ1文字のポート名は、非常にエキサイティングになるだろうされていないことをgccのC99 – ant2009

+9

注意! –

答えて

24

残念ながら、コンパイラはmain.cのコンパイル中にport_t(バイト単位)のサイズを知るためには、ヘッダファイルに完全な型定義が必要です。

+0

明らかにあなたは正しいです。 CはこれをC++とはまったく異なって扱っているようです。 –

+5

@litb:どういう意味ですか?私はC++を信じていますが、main.cppは "ports"インスタンスを作成するためにport_tの完全な定義が必要です。 –

+1

@Matthew:それはヘッダーファイルにある必要がある完全な_type_定義であることを明確にする価値があるかもしれません。変数定義はソースファイルに格納されます。 –

15

port_t構造の内部データを非表示にするには、標準ライブラリがFILEオブジェクトをどのように扱うかのようなテクニックを使用できます。クライアントコードはFILE*アイテムしか扱っていないので、実際にはFILE構造に何が含まれているかについての知識は必要ありません(実際には一般的にできません)。このメソッドの欠点は、クライアントコードでは単に変数をその型に宣言するだけではなく、ポインタを持つことができるため、APIを使用してオブジェクトを作成および破棄し、すべてオブジェクトはいくつかのAPIを経由する必要があります。

port_tオブジェクトをどのように使用する必要があるかについてきれいなインターフェースがあり、プライベートなものを非公開にすることができるという利点があります(非公開のものは、クライアントがアクセスするためのゲッター/セッター機能が必要です)。

FILE I/OがCライブラリでどのように処理されるかと同様です。

/* port.h */ 
#ifndef _PORT_H 
#define _PORT_H 
typedef struct /* Define the struct in the header */ 
{ 
    unsigned int port_id; 
    char name; 
}port_t; 
void store_port_t(port_t);/*Prototype*/ 
#endif 

/* port.c */ 
#include "port.h" 
static port_t my_hidden_port; /* Here you can hide whatever you want */ 
void store_port_t(port_t hide_this) 
{ 
    my_hidden_port = hide_this; 
} 

/* main.c */ 
#include <stdio.h> 
#include "port.h" 
int main(void) 
{ 
    struct port_t ports; 
    /* Hide the data with next function*/ 
    store_port_t(ports); 
    return 0; 
} 

ヘッダファイルで変数を定義するために、一般的によくない:

+0

FILE構造体もstdio.hにはっきりとレイアウトされています。少なくとも、私のシステムで。 "typedef struct __sFILE {...} FILE;" FILEポインタを介して内部を見る必要はありません(非常に興味深い - 読み書きするための関数ポインタなど)が、まだそこにあります。 –

+0

注:FILE *ポインタを扱い、FILE *ポインタを構造化するのではなく、 "typedef"バージョンを使用する必要があります。上記のコードには "struct port_t"が必要です。もしそれが "typedef struct port_t {...} PORT"なら、FILE *ポインタに似たPORT *ポインタを使うことができます。 –

+0

@Chris、完全に宣言する必要はありません。実装では、FILE構造体をchar [X]として標準的に定義することができます。 – paxdiablo

0

は、私は別の方法をお勧めします。あなたは、関数インタフェースでport_pを使用

/* port.h */ 
typedef struct port_t *port_p; 

/* port.c */ 
#include "port.h" 
struct port_t 
{ 
    unsigned int port_id; 
    char name; 
}; 

+1

彼はヘッダーに変数を定義していなかったので、port_t型の宣言を進めようとしていました。 –

+0

なぜ彼はget/setまたはsimulair関数を使用していないのですか...しかし、あなたが正しいです...私はちょうど提案をしています... – eaanon01

6

私が使用する一般的なソリューションを提供します。 あなたにもport.hに特別にmalloc(および無料)ラッパーを作成する必要があります。

port_p portAlloc(/*perhaps some initialisation args */); 
portFree(port_p); 
関連する問題