C 结构问题,将它们放在哪里,以及如何在标题中引用它们?

C 结构问题,将它们放在哪里,以及如何在标题中引用它们?,c,struct,header,declaration,C,Struct,Header,Declaration,好吧,我现在处于进退两难的境地,我对C语言的了解(这并不是最大的一个)和全能的谷歌似乎都不能帮我解决这个问题: 我有一些游戏原型的结构: 地图(嗯……地图……) Chara(玩家的敌人基地) 播放器(播放器) 现在的问题是:Map需要对其上的Player的引用,Player正在构建,给它一个Map和Chara,而Chara也需要Map 如果我在头文件中声明结构并用#ifndef包装它们,那么当我在其他头文件中包含头文件时,我会运行一个循环依赖循环 当我在.c文件中声明结构时,我使用了exte

好吧,我现在处于进退两难的境地,我对C语言的了解(这并不是最大的一个)和全能的谷歌似乎都不能帮我解决这个问题:

我有一些游戏原型的结构:

  • 地图
    (嗯……地图……)
  • Chara
    (玩家的敌人基地)
  • 播放器
    (播放器)
现在的问题是:
Map
需要对其上的
Player
的引用,
Player
正在构建,给它一个
Map
Chara
,而
Chara
也需要
Map

如果我在头文件中声明结构并用
#ifndef
包装它们,那么当我在其他头文件中包含头文件时,我会运行一个循环依赖循环

当我在.c文件中声明结构时,我使用了
extern struct Map
等,但随后我遇到了
不完整声明的无效使用
结构XXX的正向声明
等问题

现在是早上4点,我想花更多的时间重写引擎的东西(Python和JavaScript都已经存在了……是的,我的时间太多了!),而不是在剩下的晚上尝试所有可行的搜索词组合

我知道这可能是一件非常简单的事情,但这里有30°C,所以请宽恕我的C“技能”^^

编辑
因为我的问题使用了typedef,而caf的答案中没有包含它们,所以我不得不对它进行更多的修改,以使它能够正常工作。因此,为了帮助那些可能通过SE找到答案的人,我将添加以下代码:

map.h

typedef struct _Player Player;

typedef struct _Map {
    ...
    Player *player;
    ...
} Map;
typedef struct _Map Map;
typedef struct _Chara Chara;

typedef struct _Player {
    Chara *chara;
    ...
} Player;

Player *player_create(Map *map, int x, int y);
map.c

// include both player.h and chara.h
// include player.h, chara.h and map.h
player.h

typedef struct _Player Player;

typedef struct _Map {
    ...
    Player *player;
    ...
} Map;
typedef struct _Map Map;
typedef struct _Chara Chara;

typedef struct _Player {
    Chara *chara;
    ...
} Player;

Player *player_create(Map *map, int x, int y);
player.c

// include both player.h and chara.h
// include player.h, chara.h and map.h

确保您的引用是指针而不是对象的实际副本,并且您应该能够很好地向前声明它们。

如果您的结构仅包含指向其他结构的指针,则此操作有效:

map.h

#ifndef _MAP_H
#define _MAP_H

struct player;

struct map {
    struct player *player;
    ...
};

#endif /* _MAP_H */
#ifndef _CHARA_H
#define _CHARA_H

struct map;

struct chara {
    struct map *map;
    ...
};

#endif /* _CHARA_H */
#ifndef _PLAYER_H
#define _PLAYER_H

struct map;
struct chara;

struct player {
    struct map *map;
    struct chara *chara;
    ...
};

#endif /* _PLAYER_H */
#ifndef _MAP_H
#define _MAP_H

#include "player.h"

struct map {
    struct player p[10];
    ...
};

#endif /* _MAP_H */
字符h

#ifndef _MAP_H
#define _MAP_H

struct player;

struct map {
    struct player *player;
    ...
};

#endif /* _MAP_H */
#ifndef _CHARA_H
#define _CHARA_H

struct map;

struct chara {
    struct map *map;
    ...
};

#endif /* _CHARA_H */
#ifndef _PLAYER_H
#define _PLAYER_H

struct map;
struct chara;

struct player {
    struct map *map;
    struct chara *chara;
    ...
};

#endif /* _PLAYER_H */
#ifndef _MAP_H
#define _MAP_H

#include "player.h"

struct map {
    struct player p[10];
    ...
};

#endif /* _MAP_H */
player.h

#ifndef _MAP_H
#define _MAP_H

struct player;

struct map {
    struct player *player;
    ...
};

#endif /* _MAP_H */
#ifndef _CHARA_H
#define _CHARA_H

struct map;

struct chara {
    struct map *map;
    ...
};

#endif /* _CHARA_H */
#ifndef _PLAYER_H
#define _PLAYER_H

struct map;
struct chara;

struct player {
    struct map *map;
    struct chara *chara;
    ...
};

#endif /* _PLAYER_H */
#ifndef _MAP_H
#define _MAP_H

#include "player.h"

struct map {
    struct player p[10];
    ...
};

#endif /* _MAP_H */
如果其中一个结构包含其他结构(包括数组)的实际实例,则该结构还需要
#包含另一个头。例如,如果
map
包含一组玩家:

map.h

#ifndef _MAP_H
#define _MAP_H

struct player;

struct map {
    struct player *player;
    ...
};

#endif /* _MAP_H */
#ifndef _CHARA_H
#define _CHARA_H

struct map;

struct chara {
    struct map *map;
    ...
};

#endif /* _CHARA_H */
#ifndef _PLAYER_H
#define _PLAYER_H

struct map;
struct chara;

struct player {
    struct map *map;
    struct chara *chara;
    ...
};

#endif /* _PLAYER_H */
#ifndef _MAP_H
#define _MAP_H

#include "player.h"

struct map {
    struct player p[10];
    ...
};

#endif /* _MAP_H */

不过,你必须小心循环包含。如果您在
player.h
中包含
map.h
,则在
map.h
之前,您不能在另一个源文件中包含
player.h
——因此您不会这样做。

谢谢您的示例!第一个最终把我带到了正确的轨道上,一切都很好,现在很好:)根据问题,地图需要一个指向玩家的指针/参考。在这种情况下,第二种方法会变得更复杂,我认为需要一个正向引用。事实上,你的第二种方法被破坏了。当玩家包括地图时,定义了支付者,这意味着当地图包括玩家时,什么也不会发生。地图中任何指向玩家的引用或指针都将生成错误。@sje397:是的,我也得出了这个结论,因此进行了更新。您还可以放置一个
typedef struct foo foo
位于.h文件的开头。这样你甚至不需要到处重复
struct
关键字,只需使用字符即可。Chara肯定是我一整天看到的最烦人的东西。一个小错误:不要在你的结构中使用以u开头的名字。根据后面字符的大小写以及是否只有一个或两个下划线,它们可能会保留给C/OS实现。与其试图记住哪些是允许使用的,哪些是不允许使用的,不如完全避免以u开头的名字。多个包含防护装置也是如此。使用
\ifndef PLAYER\u H
而不是
\ifndef\u PLAYER\u H
。标准C头之所以使用_,是因为它们是编译器/操作系统的一部分,并试图避免与为您保留的名称冲突。