我在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);
}
答案 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
的大小。前向声明没有指定内存大小,定义也是如此。