头文件未正确包含

时间:2016-04-13 19:30:51

标签: c gcc header-files

我有以下两个头文件:

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

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

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参数),编译器会抛出此错误:

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

2 个答案:

答案 0 :(得分:3)

#include B.h中的A.h和A.h中的B.h(循环#include s)总是一个问题。如果你需要A.h中的B.h和B.h中来自A.h的东西,那么你必须找到一种方法来获得前瞻性声明。

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

#include "player.h"

答案 1 :(得分:0)

如果您无法避免两种类型的函数中的类型的相互引用,请考虑它们是否真的属于两个标头。也许你应该把它们放在一个标题中?毕竟,编译器总是会最终包括anywy。

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

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

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名称与变量名称分开。对两者使用相同的名称是有风险的。对tag和typedef使用相同的名称不是问题; typedef名称位于普通名称空间中,但标记名称位于单独的标记名称空间中。 (C ++在没有明确typedef操作的情况下实现了基本相同的效果:在声明struct SomeTag之后,您可以使用SomeTag来引用该类型。)