Reputation: 3874
I have the following two 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
and 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
When I run the make file, I get the following error:
player.h:10:11: error: unknown type name ‘map’
void move(map map, int move, player player);
I am relatively new programmer (in C that is) and I came here is hopes that you guys could help me figure out why the header files aren't seeing each other even though I included them. The compiler I am using is gcc, and I checked to make sure that both of the header files are included in their partner C files.
I also checked out these three posts:
Include a header in another header file
Include headers in header file?
Should I use #include in headers?
EDIT:
If I edit the map.h file as I have above (I added a player parameter to print_map and an include statement) the compiler throws this error:
player.h:12:11: error: unknown type name ‘map’
void move(map map, char* move, player player);
Upvotes: 2
Views: 2801
Reputation: 753475
If you can't avoid the mutual references to the types in the functions for the two types, consider whether they really belong in two headers. Maybe you should put them into one header? After all, the compiler is always going to end up including both anywy.
Alternatively, consider using opaque types:
When using opaque types, you use pointers to those types in the interfaces to functions. Adapting your code:
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
The arguments are now pointers to maps or pointers to players, not direct copies of the structures.
Either file (or both files) can be specified in a source file using these, and the code will compile with both. Note, too, that I've separated the typedef names from the variable names. Using the same name for both is risky. Using the same name for the tag and the typedef is not a problem; the typedef names are in the ordinary namespace but the tag names are in the separate tag namespace. (C++ achieves essentially the same effect without an explicit typedef
operation: after declaring struct SomeTag
, you can use SomeTag
to refer to the type.)
Upvotes: 0
Reputation: 206557
#include
ing A.h in B.h and B.h in A.h (circular #include
s) is always a problem. If you need something from B.h in A.h and something from A.h in B.h, you'll have to find a way get by with forward declarations.
In your case, you are not using anything from player.h in map.h. Simply remove the following line from map.h.
#include "player.h"
Upvotes: 3