【问题标题】:Header Files not including correctly头文件未正确包含
【发布时间】:2016-08-05 02:37:06
【问题描述】:

我有以下两个头文件:

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

ma​​p.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.h:12:11: error: unknown type name ‘map’
 void move(map map, char* move, player player);

【问题讨论】:

  • 请不要将变量命名为与其类型相同。
  • 对不起,个人习惯.....我正试图杀死它,但对于程序员创建的类型,真的很难不这样做。
  • 实际上很容易不这样做,通过使用诸如map_tplayer_t 之类的命名约定。
  • 多余的“_t”是什么意思?
  • 它会告诉我map_t 是一种类型,并将其与map 等实例区分开来。例如,假设你有map *map,然后你想要sizeof(map),你期望会发生什么?

标签: c gcc header-files


【解决方案1】:

#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"

【讨论】:

  • 谢谢!我不完全明白为什么会这样,如果不使用它不应该忽略它吗?
  • @Steampunkery,处理#include 语句和编译代码是在两个完全独立的不同步骤中完成的。您的问题的答案是:“不,处理器不能忽略 #include 语句。”
  • 查看编辑,我只是​​需要在 map.h 中使用 player.h
  • 您不能在 player.h 中使用 map,在 map.h 中使用 player。您必须在其中一个中使用指针 - 在 player.h 中使用 map* 或在 map.h 中使用 player*
【解决方案2】:

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

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

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

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来引用类型。)

【讨论】:

    猜你喜欢
    • 2010-11-15
    • 1970-01-01
    • 2017-08-27
    • 2014-04-28
    • 1970-01-01
    • 2015-01-12
    • 2023-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多