我有3个源文件:matrix.c,tetramino.c和learntris.c(包括标题tetramino.h
和matrix.h
,将它与相应的文件相关联)。我有一个结构:struct tetramino
在所有这些文件中都需要。在阅读了这个问题及其答案 - How to use a defined struct from another source file?后,我创建了一个头文件structure.h
,现在我的文件看起来像这样:
在structure.h中:
typedef struct tetramino
{
int type;
char *p;
}tetramino;
在matrix.h中:
#include"structure.h"
int print_matrix(void);
int clear_matrix(void);
在tetramino.h中:
#include"structure.h"
int rotate(void);
int set_tetramino(void);
最后,在主要的learntris.c文件中包含:
#include"structure.h"
#include"matrix.h"
#include"tetramino.h"
现在,在编译它们时,我得到了这些错误:
错误:重新定义'struct tetramino'
和
错误:'tetramino'的冲突类型
问题出在哪里?
答案 0 :(得分:3)
当您在所有文件中#include <structure.h>
时,每次都包含它们。这导致它每次都尝试定义结构。
使用包含警戒来确保头文件包含一次。
#ifndef STRUCTURE_H
#define STRUCTURE_H
typedef struct tetramino
{
int type;
char *p;
}tetramino;
#endif /* STRUCTURE_H */
建议在所有头文件中使用防护,但这不是必须的,但这是一种非常好的做法。
如Neroku所述,您可以使用#pragme once
代替。阅读更多here。
答案 1 :(得分:2)
除了警卫,其他答案解释说,在.h文件中包含.h文件不是一个好习惯,因为你现在无法控制它们被包含的顺序。此外,对.h文件的更改现在可能导致所有需要重新编译的c文件,即使它们不受更改影响(即,您创建了不必要的依赖项)。
您应该在C文件中包含structure.h
,然后在C文件需要了解结构时只包含 。
答案 2 :(得分:1)
每个标头文件should have the following structure:
#ifndef TETRAMINO_STRUCTURE_H
#define TETRAMINO_STRUCTURE_H
struct tetramino { ... };
#endif
这意味着头文件的主要部分仅评估一次。名称TETRAMINO_STRUCTURE_H
由项目名称,文件名和尾随H
组成,意思是标题。
其次,由于函数声明不需要tetramino
类型,因此您不需要#include "structure.h"
。您只需要在相应的.c
文件中使用这些行。
答案 3 :(得分:1)
#include
将包含文件的内容直接粘贴到#include
指令的位置。因此,在您的示例中,您最终会得到相同结构声明的3倍。
这方面的标准解决方案是保护宏:
#ifndef EXAMPLE_HEADER_FILE_H
#define EXAMPLE_HEADER_FILE_H
struct exampleStruct
{
// ...
};
#endif
这样,只有第一个#include
会实际粘贴声明,每个连续的#include
都会导致预处理器跳过整个标头,因为已经定义了保护宏。