我有以下两个头文件:
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);
答案 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
来引用该类型。)