头文件没有正确包含

Header Files not including correctly

我有以下两个头文件:

player.h

#ifndef _PLAYER_H_
#define _PLAYER_H_
#include "map.h"

typedef struct{
    char* name;
    int x;
    int y;
    int keyMapping;
    char symbol;
}player;
void move(map map, char* move, player player);
void setKeyMapping(int keyMap, player player);
void initPlr(char* name, int x, int y, player player);
#endif

map.h

#ifndef _MAP_H_
#define _MAP_H_
#include "player.h"

typedef struct{
    char** levelData;
    int width;
    int height;
}map;
void init(map* map,int height, int width);
void print_map(map map, player player);
void resume(const char *resFrom, map map);
void save(const char *saveTo, map map);

#endif

当我运行生成文件时,出现以下错误:

player.h:10:11: error: unknown type name ‘map’
 void move(map map, int move, player player);

我是一个相对较新的程序员(在 C 语言中),我来到这里是希望你们能帮助我弄清楚为什么即使我包含了头文件也看不到彼此。我使用的编译器是 gcc,我检查以确保这两个头文件都包含在它们的伙伴 C 文件中。

我也查看了这三个帖子:

Include a header in another header file

Include headers in header file?

Should I use #include in headers?

编辑:

如果我像上面那样编辑 map.h 文件(我向 print_map 添加了一个播放器参数和一个 include 语句),编译器会抛出此错误:

player.h:12:11: error: unknown type name ‘map’
 void move(map map, char* move, player player);

#includeing A.h in B.h 和 B.h in A.h(循环 #includes)总是一个问题。如果您需要 A.h 中的 B.h 中的内容以及 B.h 中的 A.h 中的内容,您将必须找到一种通过前向声明的方法。

在您的情况下,您没有在 map.h 中使用 player.h 中的任何内容。只需从 map.h.

中删除以下行
#include "player.h"

如果无法避免两个类型在函数中类型的相互引用,请考虑它们是否真的属于两个header。也许你应该把它们合二为一 header?毕竟,编译器总是会以任何方式包括两者。

或者,考虑使用不透明类型:

使用不透明类型时,您可以在函数接口中使用指向这些类型的指针。调整您的代码:

map.h

#ifndef MAP_H_INCLUDED
#define MAP_H_INCLUDED

struct Map;
struct Player;

#include "player.h"

typedef struct Map {
    char** levelData;
    int width;
    int height;
} Map;

void init(struct Map* map,int height, int width);
void print_map(struct Map *map, struct Player *player);
void resume(const char *resFrom, struct Map *map);
void save(const char *saveTo, struct Map *map);

#endif

player.h

#ifndef PLAYER_H_INCLUDED
#define PLAYER_H_INCLUDED

struct Map;
struct Player;

#include "map.h"

typedef struct Player{
    char* name;
    int x;
    int y;
    int keyMapping;
    char symbol;
} Player;

void move(struct Map map, char* move, struct Player *player);
void setKeyMapping(int keyMap, struct Player *player);
void initPlr(char* name, int x, int y, struct Player *player);

#endif

参数现在是指向地图或玩家的指针,而不是结构的直接副本。

可以使用这些文件在源文件中指定其中一个文件(或两个文件),并且代码将与这两个文件一起编译。另请注意,我已将 typedef 名称与变量名称分开。两者使用相同的名称是有风险的。为标签和 typedef 使用相同的名称不是问题; typedef 名称位于普通名称空间中,但标签名称位于单独的标签名称空间中。 (C++ 在没有显式 typedef 操作的情况下实现了基本相同的效果:在声明 struct SomeTag 之后,您可以使用 SomeTag 来引用类型。)