2017-02-15 10 views
4

C言語では、ファイルf.cの中にstruct sを定義するとします。このstructに他の人がアクセスできるようにしたくないので、f.hに入れないでください。私のプロジェクトでは、g.cを含む他の多くのファイルがstruct sf.cにアクセスしたいと思っています。他のファイルからヘッダーにアクセスできない構造体を作成する

これを可能にする方法はありますか?私はsがで宣言されたグローバルextern変数でなければならないと考えています。コンパイル時にリンクされます。私はこれが可能かどうか、またはこのようなことをやり遂げる正しい/最善の方法であるかどうかはわかりません。

+0

タイプの定義は、その使用の前に利用可能でなければなりません。ヘッダーを使用するか、構造体の定義を貼り付けてコピーします。翻訳単位間で型を共有する方法はありません。 – DeiDei

+1

この構造体を作成して変更するには、 'f.c'にAPIを作成する必要があります。呼び出し元に 'void * 'を渡して、フィールドにアクセスすることはできません。 –

+3

他の人がアクセスできる*を定義する*。 – rustyx

答えて

4

ヘッダーファイルに型への前方宣言を追加することができます。これは不透明(不完全)型として扱うことができます。

struct s; 

他の人々は今struct s *を参照することができますが、型はそれらに不完全であるため、彼らは、struct sを使用することはできません。

APIを提供する場合、APIを呼び出してstruct sのインスタンスを作成、変更、破棄することができます。これを行うには

enum struct_s_field { 
    S_FIELD_NAME, 
    S_FIELD_VALUE, 
    /* ... */ 
}; 

struct s * make_s(); 
void unmake_s(struct s *); 
void update_s(struct s *, enum struct_s_field, ...); 
1

一つの方法は、初期化することf.cにAPIを作成、読み取り、およびstruct s構造を記述することです。この構造体の内容を呼び出し元から隠すには、void *を、後でf.c APIの呼び出しで使用する呼び出し元に戻します。例えば

void *pS; 

pS = sInit(); 

void *sInit(void) 
{ 
    return malloc(sizeof(struct s)); 
} 
+0

@Downvoter: 'void *'戻りポインタの何が問題になっていますか? – d3L

+2

@ d3l 'void *'は型システムの穴です。 Cのオブジェクトポインタは、あらゆる型のキャストを必要とすることなく、暗黙のうちに 'void *'との間で変換されます。なぜ@ jxhの答えのように、宣言されているが定義されていない構造体へのポインタを使うことができるときに、そのような穴を作るのですか? – PSkocik

+0

ええ、それは良い点です。 – d3L

関連する問題