如何解决C 中的相互依赖结构
我正在关注 Ruslan Spivak 的文章系列/教程“让我们构建一个简单的解释器”,这是在 Python 中构建一个简单的 Pascal 解释器的指南。我正在尝试使用 C。我对添加抽象语法树的部分感到困惑。
#include "tokens.h"
struct binopnode
{
struct node left;
token op;
struct node right;
};
struct node
{
union nvalue value;
enum ntype type;
};
enum ntype
{
NUM,BInop,};
union nvalue
{
struct binopnode binop;
struct numnode num;
};
struct numnode
{
token tok;
};
其中 "tokens.h"
包括 token
typedef
的结构。
我的问题是我的编译器:
Apple clang version 12.0.5 (clang-1205.0.22.9)
Target: x86_64-apple-darwin20.3.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLinetools/usr/bin
抛出 Incomplete Type
个错误。
来自这些链接:
http://c-faq.com/decl/mutrefstructs.html
Circular definition in C
我的猜测是我必须使用指针,但我完全不知道在哪里。
解决方法
您可以先声明结构,然后再将它们作为指针引用。
在 C 中,当一个结构体 A 包含另一个结构体 B 时,A 将需要用于 B 大小的内存区域。如果结构体 A 包含结构体 B,而结构体 B 包含结构体 A,编译器无法决定它应该分配多少内存每个结构。所以如果你想使用相互引用的结构体,你应该至少使用它们中的一个作为指针。
#include "tokens.h"
struct binopnode;
struct node;
enum ntype;
union nvalue;
struct numnode;
struct binopnode
{
struct node *left;
token op;
struct node *right;
};
struct node
{
union nvalue *value;
enum ntype type;
};
enum ntype
{
NUM,BINOP,};
union nvalue
{
struct binopnode *binop;
struct numnode *num;
};
struct numnode
{
token tok;
};
,
在 Python 中,对象不能包含其他对象。 Python 中的对象只能包含对另一个对象的引用。
因此,在 Python 中,类 BinOp
的对象包含三个引用 - self.left
、self,right
和 self.op
。但它实际上并不包含三个对象。
在C
中,一个结构体实际上可以包含其他结构体。因此,struct binop
类型的对象(在 C 中,“对象”一词仅表示解释为特定类型的内存区域 - 不像 Python 对象)将包含两个 struct node
类型的对象以及 token
类型之一。
在 C 中,所有类型都必须有大小。让我们找到一些大小的下限(这些只是下限,因为我们必须考虑填充)。
sizeof(struct binop) >= sizeof(struct node) + sizeof(token) + sizeof(struct node)
sizeof(struct node) >= sizeof(union nvalue) + sizeof(enum ntype)
sizeof(union nvalue) >= min(sizeof(struct binop),sizeof(struct numnode)) >= sizeof(struct binop)
所以我们知道 sizeof(struct binop) >= sizeof(struct node) + sizeof(token) + sizeof(struct node) > sizeof(struct node) >= sizeof(union nvalue) >= sizeof(struct binop)
。
因此,sizeof(struct binop) > sizeof(struct binop)
。
这是一个问题,因为一个数字不能大于它自己。因此 C
无法为您编译此代码,因为它不知道 struct binop
应该有多大。
事实上,任何时候 struct
以这种方式包含自己,没有指针,这将导致严重的问题。
好消息是我们可以通过重新定义来打破这个循环
union nvalue {
struct binopnode* binop,struct numnode num
}
现在,我们将能够将 union nvalue
的大小计算为 min(sizeof(struct binopnode*),sizeof(struct numnode))
。这完全没问题,因为指针具有固定大小(在 64 位系统上,除函数指针之外的任何指针的大小都是 8
,无论它指向什么)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。