2

これが私のセットアップです:

public.h:

#ifndef PUBLIC_H_
#define PUBLIC_H_

#include "func.h"

/*extern typedef struct _my_private_struct PRIVATE_;*/
typedef struct _my_private_struct PRIVATE_; /* Thanks to larsmans and Simon Richter */
#endif

struct.h で

#ifndef STRUCT_H_
#define STRUCT_H_

struct _my_private_struct {
    int i;
};
#endif

func.h で:

#ifndef FUNC_H_
#define FUNC_H_
#include "struct.h"

/* typedef struct _my_private_struct PRIVATE_; */
extern PRIVATE_ * get_new(int);
#endif

func.c:

#include <stdlib.h>
#include "func.h"

PRIVATE_ * get_new(int i)
{
    PRIVATE_ *p = (PRIVATE_ *) malloc(sizeof(PRIVATE_));
    if (p == NULL) return NULL;

    p->i = i;

    return p; 
}

main.c で:

#include "public.h"

int main(int argc, char ** argv)
{
    PRIVATE_ *p = get_new(2);
    return 0;
}

これらのファイルを GCC でコンパイルすると、次のエラーが発生します。

古いコンパイル エラー

宣言指定子の複数のストレージ クラス

編集後のコンパイル エラー

「*」トークンの前に「=」、「,」、「;」、「asm」、または「__attribute__」が必要です

誰かが私を助けてくれたり、なぜ私がこれを手に入れたのか、それを修正する方法を説明できますか?

4

4 に答える 4

6

他の答えはあなたの問題をかなりうまくカバーしています。ただし、それらに追加して、最新のコメントに答えさせてください。

コンパイル エラーが発生しています: public.h: typedef PRIVATE_ の再定義...

エラーは自明ですが、なぜそれが起こっているのかはおそらくあまり明確ではありません。public.h をインクルードするとどうなるか考えてみましょう:

#include "struct.h"
#include "func.h"
typedef struct _my_private_struct PRIVATE_;

これをトレースしてプリプロセッサを完全に展開すると、次のようになります。

// struct.h
struct _my_private_struct
{
    int i;
};

// func.h
typedef struct _my_private_struct PRIVATE_;
extern PRIVATE_ * get_new(int);

// public.h
typedef struct _my_private_struct PRIVATE_;

問題が発生している理由が明らかになったはずです。func.h に typedef がない場合、get_newプロトタイプはPRIVATEまだ確認されていないため失敗します。OTOH、typedef をそのままにしておくと、2 回定義したことになります。

また、その構造を他のコードやモジュールから非公開にしようとしているようです。ビルド エラーを修正しても、そのカプセル化は実際には達成されていません。このことを考慮:

int main()
{
    PRIVATE_ *p = get_new(2);
    p->i = 1337;        // HAHA, I just modified your private i.
                        // what are you going to do about it?
}

C でデータのプライバシーが必要な場合は、不透明なポインターの設計を検討してください。ソースを次のように再構築することをお勧めします。

// public.h
#ifndef PUBLIC_H_
#define PUBLIC_H_

#include "func.h"

#endif

// func.h
#ifndef FUNC_H_
#define FUNC_H_

struct PRIVATE_NOT_ACCESSIBLE;
typedef struct PRIVATE_NOT_ACCESSIBLE myint_t;

// declare your struct methods here
myint_t* get_new(int);
// ..

#endif

// func.c
#include <stdlib.h>
#include "func.h"

// define this only with functions 
// that's suppose to work with its internal data
struct PRIVATE_NOT_ACCESSIBLE
{
    int i;
};

myint_t * get_new(int i)
{
  // ...
}

これを試してみると:

#include "public.h"

int main()
{
    myint_t *p = get_new(2);
    p->i = 1337;            // Aw, doesn't work anymore :(
}

編集:以下のOPのコメントに答える。

private 構造体のメソッドが複数のコンパイル ユニットに実装されている場合でも、private の定義を専用のヘッダーに移動することで機能させることができます。

// func_implementation.h
#include "func.h"
struct PRIVATE_NOT_ACCESSIBLE
{
    int i;
};
// internal methods, helper functions you don't want exposed should go here too.
// eg.
void helper_method(myint_t *);

struct private 'object' を実装するソース ファイルには、'func_implementation.h' が含まれます。private を使用する外部クライアント コードには、「func.h」のみが含まれます。

于 2011-12-05T01:09:34.527 に答える
5
  • typedefステートメントは次のように終了する必要があります;
  • extern typedef意味がありませんtypedef
于 2011-12-04T19:29:27.410 に答える
2

現在の構文は正しくありません。typedef と構造体の後にセミコロンを付ける必要があります。

于 2011-12-04T19:29:51.607 に答える
1

';'があります typedefの後にありません。

編集:

struct _my_private_struct {...};

先頭にアンダースコアが付いた名前は使用しないでください。それらは言語または実装のために予約されています。

于 2011-12-04T19:34:11.927 に答える