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 失败:错误:返回类型是不完整的类型

我有点理解问题所在,但有解决方法吗?

4

2 回答 2

3

您需要了解struct foo_structfoo.c 外部的定义,从而打破了您的抽象。使结构定义对特定源文件“私有”的全部目的是使其他源文件不知道也不能struct foo_struct直接操作其成员。

您要么需要bar进入 foo.c,要么需要将结构定义放入foo.h(使其公开),或者您需要定义一个接口,允许其他翻译单元分配、设置、读取和解除分配类型的项目,foo_s而无需暴露其类型的细节,类似于stdio.h操作类型对象的例程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);
  }
}

可能有一百种更好的方法可以做到这一点,但你应该明白这一点。

于 2012-09-27T14:10:08.717 回答
1

不,没有简单的解决方法。

在这段代码中

typedef struct foo_struct foo_s; 

foo_s fb;
fb.b = b;

编译器只知道这foo_s是一个结构,但它不知道是否b是该结构的成员,或者结构有多大。而且它绝对不知道它是您要为其分配值的第二个成员,因此它不起作用。

如果您包含结构的定义,编译器只能告诉代码应该做什么。

于 2012-09-27T14:09:48.940 回答