防止递归 C #include
我大致了解 #include 对 C 预处理器所做的规则,但我并不完全理解它。现在,我有两个头文件,Move.h 和 Board.h,它们都 typedef 各自的类型(Move 和 Board)。在两个头文件中,我需要引用另一个头文件中定义的类型。
现在我在 Board.h 中有#include“Move.h”,在 Move.h 中有#include“Board.h”。当我编译时,gcc 翻转并给我一个很长的(看起来像无限递归的)错误消息,在 Move.h 和 Board.h 之间翻转。
如何包含这些文件,以便我不会无限期地递归包含?
I roughly understand the rules with what #include does with the C preprocessor, but I don't understand it completely. Right now, I have two header files, Move.h and Board.h that both typedef their respective type (Move and Board). In both header files, I need to reference the type defined in the other header file.
Right now I have #include "Move.h" in Board.h and #include "Board.h" in Move.h. When I compile though, gcc flips out and gives me a long (what looks like infinite recursive) error message flipping between Move.h and Board.h.
How do I include these files so that I'm not recursively including indefinitely?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您需要查看前向声明,您已经创建了包含的无限循环,前向声明是正确的解决方案。
下面是一个例子:
Move.h
Board.h
main.c
注意:每当你创建一个“Board”时,你都需要做这样的事情(有几种方法,这里是一个例子):
You need to look into forward declarations, you have created an infinite loops of includes, forward declarations are the proper solution.
Here's an example:
Move.h
Board.h
main.c
Note: whenever you create a "Board", you will need to do something like this (there are a few ways, here's an example):
包括警卫将是解决此问题的一部分。
维基百科的示例:
http://en.wikipedia.org/wiki/Include_guard
另一部分正如其他几个人所指出的那样,这是前向引用。 (http://en.wikipedia.org/wiki/Forward_Reference)
您可以部分声明一个另一个结构之上的结构如下:
Include guards would be part of the solution to this issue.
Example from wikipedia:
http://en.wikipedia.org/wiki/Include_guard
The other part as noted by several others is forward referencing. (http://en.wikipedia.org/wiki/Forward_Reference)
You can partially declare one of the structures above the other one like so:
像这样:
这样
Board.h
可以在不依赖move.h
的情况下编译,并且您可以包含move 中的
使其内容在那里可用。board.h
.hLike so:
This way
Board.h
can be compiled without dependency onmove.h
and you can includeboard.h
frommove.h
to make its content available there.首先,您的
.h
文件中似乎缺少 includeguards ,所以你递归地包含它们。那很糟糕。其次,您可以进行前瞻性声明。在
Move.h
中:在
Board.h
中:请注意,如果需要声明
struct Move
和struct Board
如果两个文件中都存在对象(而不是指向其中之一的指针),则此方法将不起作用。这是因为在解析其中一个文件时,其中一种类型是不完整类型(上例中的struct Move
)。因此,如果您需要使用这两个文件中的类型,则必须分离出类型定义:具有定义
struct Move
和struct Board
的头文件,以及没有别的(就像我上面的例子一样),然后使用另一个引用struct Move
和struct Board
的头文件。当然,您不能让
struct Move
包含struct Board
并且struct Board
包含struct Move
同时,这将是无限递归,并且结构大小也将是无限的!First, you seem to lack include guards in your
.h
files, so you're including them recursively. That is bad.Second, you can do a forward declaration. In
Move.h
:In
Board.h
:Note that if you need to declare
struct Move
andstruct Board
objects (rather than pointer to one of them) in both the files, this method won't work. This is because one of the types is an incomplete type at the time of parsing of one of the files (struct Move
in the above example).So, if you need to use the types in both the files, you will have to separate out the type definitions: have header files that define
struct Move
andstruct Board
, and nothing else (something like my example above), and then use another header file that references bothstruct Move
andstruct Board
.Of course, you can't have
struct Move
contain astruct Board
andstruct Board
contain astruct Move
at the same time—that will be infinite recursion, and the struct sizes will be infinite as well!您首先需要拥有其中之一。在其中之一中进行前向声明,并将该声明作为例如
board.h 文件的一部分。
并且
可以是 move.h 文件的一部分,
然后您可以按任一顺序添加它们。
编辑
正如评论中指出的那样...我假设对板结构使用 typedef 构造如下,
因为我从未见过有人在没有 typedef 的情况下使用 C 中的结构我做了这个假设...也许事情已经改变了自从我上次用 C 编写代码以来(哎呀......那是 15 年前的事了)
You need to have one of them first. Make a forward decl in one of them and have that one for for example
could be part of the board.h file.
and
could be part of the move.h file
then you could add them in either order.
edit
As was pointed out in the comments... I was assuming the use of the typedef construct as follows for the board struct
since I've never seen anyone using structs in C without a typedef I made this assumption... maybe things have changed since the last time I coded in C (yikies.... it was like 15 years ago)
循环依赖是一件令人头疼的事,应该尽可能消除。除了到目前为止给出的前向声明建议(Alok 的就是最好的例子)之外,我还想提出另一个建议:通过引入第三种类型(将其称为 BoardMoveAssoc 进行说明)来打破 Board 和 Move 之间的相互依赖;我相信你可以想出一个不那么糟糕的名字):
在这个方案下,Board 和 Move 不需要互相了解任何信息;两者之间的任何关联均由 BoardMoveAssoc 类型管理。确切的结构取决于 Move 和 Board 的关联方式;例如,如果多个动作映射到单个棋盘,则结构可能看起来更像
这样,您不必担心前向声明或不完整的类型。您正在将第三种类型引入其中,但我相信这会更容易理解和维护。
Circular dependencies are a pain in the ass and should be eliminated wherever feasible. In addition to the forward declaration suggestions given so far (Alok's is the best example), I'd like to throw another suggestion into the works: break the mutual dependency between Board and Move by introducing a third type (call it BoardMoveAssoc for illustration; I'm sure you can come up with a less sucky name):
Under this scheme, Board and Move don't have to know anything about each other; any associations between the two are managed by the BoardMoveAssoc type. The exact structure will depend on how Move and Board are supposed to be related; e.g., if multiple moves are mapped to a single board, the structure may look more like
This way, you don't have to worry about forward declarations or incomplete types. You are introducing a third type into the mix, but I believe this will be easier to understand and maintain.
来自 K&R C 编程语言(我的副本中的第 91 页“条件包含”),为您做了一些调整:
对于 Move.h 也是如此
,一旦包含一次标头,就不会包含它再次,因为已经为预处理器定义了“BOARD_H”名称。
From K&R The C Programming Language (p 91 "Conditional Inclusion" in my copy), with some tweaks for you:
and the same for Move.h
In this way, once a header has been included once, it will not be included again, as the 'BOARD_H' name has already been defined for the preprocessor.