4

構造体変数を宣言するヘッダーファイルfoo.hがあるとしましょう

#include <stdio.h>

typedef struct foo_struct foo_s;

foo_s foo_function(int a);
foo_s bar_function(int b);

そして、実際に構造を定義するソースファイルfoo.c

#include "foo.h"

struct foo_struct
{
   int a;
   int b;
};

foo_s foo_function(int a)
{
    foo_s fs;
    fs.a = a;
    return fs;
}

ここで、別のソース ファイルbar.cのfoo.cで定義された構造にアクセスしたいので、次のことを試します。

#include "foo.h"

foo_s bar_function(int b)

{
  foo_s fb;
  fb.b = b;

  return fb;
}

...そしてbar.c:3:7: error: return type is an incomplete typeで失敗します

問題の内容は理解できましたが、回避策はありますか?

4

2 に答える 2

3

struct foo_structfoo.cの外側の定義を知る必要があるため、抽象化を破っています。構造体定義を特定のソース ファイルに対して「プライベート」にすることの要点は、他のソース ファイルが のメンバーを認識せず、struct foo_struct直接操作できないようにすることです。

barfoo.cに移動するか構造体定義を配置するfoo.h(パブリックにする)必要があるfoo_s、他の翻訳単位がタイプのアイテムを割り当て、設定、読み取り、および割り当て解除できるようにするインターフェイスを定義する必要があります。のルーチンstdio.hが type のオブジェクトを操作する方法と同様に、その型の詳細を公開しFILEます。

foo_s *create_foo(int a, int b);
void set_foo(foo_s *f, char *property, int value);
int get_foo(foo_s *f, char *property);
void destroy_foo(foo_s **f);  // sets f to NULL after deallocation.

上記のインターフェースを foo.h に追加し、それを foo.c に実装します。他の翻訳単位 (ソース ファイル) の関数は、次のように使用します。

void blah(void)
{
  foo_s *f = create_foo(0,0);
  if (f)
  {
    set_foo(f, "a", 1);
    set_foo(f, "b", 2);

    printf("a = %d, b = %d\n", get_foo(f, "a"), get_foo(f, "b");
    destroy_foo(&f);
    assert(f == NULL);
  }
}

それを行うためのより良い方法はおそらく100ありますが、アイデアを得る必要があります.

于 2012-09-27T14:10:08.717 に答える
1

いいえ、簡単な回避策はありません。

このコードでは

typedef struct foo_struct foo_s; 

foo_s fb;
fb.b = b;

コンパイラはそれが構造体であることだけを認識していますが、がその構造体のメンバーであるかどうか、または構造体の大きさはfoo_sわかりません。bそして、それが値を割り当てたい 2 番目のメンバーであることを確実に認識できないため、機能しません。

コンパイラは、構造体の定義を含めた場合にのみ、コードが何をすべきかを知ることができます。

于 2012-09-27T14:09:48.940 に答える