为什么结构的前向声明不起作用?

时间:2014-06-05 08:57:55

标签: c struct forward-declaration

我在C中编写了一个小代码,其中定义了两个结构类型,它们在定义中具有彼此的成员。情况1:如果在struct bar之前定义了struct foo,则按预期编译代码。情况2:如果在struct bar之后定义了struct foo,它将无法编译,这也是预期的,因为无法知道struct foo变量的内存要求。但我希望如果在案例2中使用struct foo的前向声明它将会编译。但它不起作用。我错过了什么?

#include<stdio.h>
#include<stdlib.h>

struct foo; // forward declaration

struct bar
{
  int a;
  struct bar *next;
  struct foo ch;
};

struct foo
{
  struct bar *n;
  struct foo *nx;
};


int main()
{
  struct bar p;
  return(0);
}

4 个答案:

答案 0 :(得分:3)

前向声明仅通知编译器有一些名为foo的东西,它没有说明大小。 您可以使用foo*,因为这是一个已知大小但不是foo本身的指针,因为大小是unknwon,所以编译器不知道bar的内存布局应该是什么样子。

编译器只对您的文档进行一次传递。所以它无法知道前面定义的结构。

答案 1 :(得分:1)

如果结构类型X在结构声明或其函数中仅作为指针类型出现,并且头文件中的代码不会尝试访问X的任何成员变量,那么您不应该#include Xh,而是做一个不完整的X声明(也称为 在第一次使用X之前的“转发”声明。这是一个结构类型Thing通过指针引用X的示例:

struct X;  /* incomplete ("forward") declaration */

struct Thing {
  int i;
  struct X* x_ptr;
};

编译器很乐意接受包含指向不完全已知结构类型的指针的代码,主要是因为无论指针指向什么,指针总是具有相同的大小和特征。通常,只有.c文件中的代码需要访问X的成员(或大小),因此.c文件将#include“X.h”。这是一种封装模块并将其与其他模块分离的强大技术。

也就是说,如果您的代码类似于:

,它将正常工作
#include<stdio.h>
#include<stdlib.h>

struct foo; // forward declaration

struct bar
{
  int a;
  struct bar *next;
  struct foo *ch;       /* MODIFIED LINE */
};

struct foo
{
  struct bar *n;
  struct foo *nx;
};


int main()
{
  struct bar p;
  return(0);
}

但在你的情况下,struct bar有一个struct foo类型的“元素”。因此它会给出错误字段不完整的类型。

另外,请参阅以下代码段(完美无缺):

#include<stdio.h>
#include<stdlib.h>

struct bar
{
  int a;
  struct aabar *next;  /* MODIFIED LINE - aabar never declared */
  struct foo *ch;
};

struct foo
{
  struct bar *n;
  struct foo *nx;
};

int main()
{
  struct bar p;
  return(0);
}

答案 2 :(得分:0)

声明也不能让编译器知道如何分配内存。

答案 3 :(得分:0)

struct foo元素中nx是一个指针,因此定义struct foo并不需要memery大小。但是,在struct bar上,元素ch不是指针,因此定义struct bar需要知道struct foo的大小。前向声明没有指定内存大小,定义也是如此。