【问题标题】:When I compile in C I have an error of imports in header files当我在 C 中编译时,头文件中出现导入错误
【发布时间】:2016-07-03 06:40:43
【问题描述】:

我在编译我的项目时遇到了下一个错误。

./PC.h:15:12: error: unknown type name 'InstructionMemory'
PC *new_pc(InstructionMemory *memoria);
           ^
./PC.h:17:1: error: unknown type name 'InstructionMemory'
InstructionMemory *get_memory(PC *programCounter);
^
2 errors generated.
In file included from main.c:5:
./InstructionRegister.h:7:36: error: unknown type name 'BankRegister'
int opera(InstructionRegister *IR, BankRegister *bank);

但这对我没有意义,我查看文件并且它们是头文件,所以我知道您不能在头文件中使用#include。所以我不知道我做错了什么。

有我的PC.h文件的内容:

typedef struct PC PC;
PC *new_pc(InstructionMemory *memoria);
int getpc(PC *programCounter);
InstructionMemory *get_memory(PC *programCounter);
char *fecth(PC *programCounter);
char *linea_actual(PC *programCounter);

我使用下一个makefile来编译:

CC = gcc
CFLAGS=-I
DEPS = ALU.h InstructionRegister.h Rebasing.h BankRegister.h MemoryInstruction.h ControlUnit.h PC.h

run: exect
    ./exect $(EX)

%.o: %.c $(DEPS)
    $(CC) -c $< $(CFLAGS)

exect: ALU.c InstructionRegister.c Rebasing.c BankRegister.c MemoryInstruction.c main.c ControlUnit.c PC.c
    gcc -o exect InstructionRegister.c Rebasing.c BankRegister.c MemoryInstruction.c main.c ControlUnit.c PC.c -I.


clean:
    rm -f *.o

【问题讨论】:

  • PC.h 需要包含定义 InstructionMemory 的任何内容。或者使用前向声明
  • 你不需要编译头文件。
  • "我知道你不能在头文件中使用#include" - 是的,你可以。
  • “我知道你不能在头文件中使用#include”。谁说的?
  • 感谢大家的回复。

标签: c makefile compilation compiler-errors


【解决方案1】:

所以我知道你不能在头文件中使用#include

你错了。您可以并且经常应该并且想要在头文件中使用多个include directives

一个典型的小型 C 项目(例如总共不到十万行 C 代码)通常会有一个单个通用头文件,例如myheader.h,通常以 include guard 开头,并包含多个系统,所以喜欢

#ifndef MYHEADER_INCLUDED
#define MYHEADER_INCLUDED

// some system includes
#include <stdio.h>
#include <stdlib.h>

/// your type declarations
enum foo_en { /* blablabla */ };
struct bar_st { /* blablabla */ };
typedef struct bar_st Bar;
/* etc... */

/// your global functions 
extern int myglobfun(int, int);
/* etc...*/

/// your global variables (have only a few of them)
extern Bar*my_bar;
/* etc... */

#endif /*MYHEADER_INCLUDED*/

这只是组织项目的一种可能性。有些人喜欢在他们的每个翻译单元(例如 C 源文件)中拥有许多头文件和明确的 #include 系统头文件,然后是他们自己的头文件。

拥有单个公共标头的优点是Makefile 易于编码,您甚至可以使用precompile 您的公共标头。缺点是该标头中的任何更改(例如,在公共 struct 中添加字段)都会强制 make 重新编译所有内容(对于小项目来说不是什么大问题)。

或者你可以有很多头文件,然后确保在其中使用include guards(在单个常见的头文件中它实际上是无用的,但不会造成伤害),并定义一个关于多重包含的规则。通常,头文件本身会包含其他需要的头文件,或者检查它们是否已被包含,例如与

 // file "myheaderone.h"
 #ifndef MYHEADERONE_INCLUDED

 // check that "myotherheader.h" has been included
 #ifndef MYOTHERHEADER_INCLUDED
 #error myotherheader.h should have been #include-d
 #endif

 //// etc

或者,您可以在myfirstheader.h 的开头附近编码#include "myotherheader.h"

如果您有多个标头,则需要一个复杂的Makefile,并且您宁愿生成依赖项,请参阅this。它使用了一些preprocessor optionsgcc,比如-M 和朋友。

顺便说一句,您的Makefile 是错误的。不要在其中硬编码cc(但使用$(CC))。成为sureGCC 询问所有警告和调试信息(例如CFLAGS= -Wall -g)。通过运行make -p 了解 GNU make catalog of rules。而且您的CFLAGS= -I 确实是错误的,您可能想要CFLAGS= -I. -Wall -g,因为-I 应该始终后跟一个目录。

PS。如果使用gcc,请养成总是-Wall 传递给它的习惯。很多时候(当然在你的情况下)你也想要-Wextra(得到更多警告;记住编译器警告是你的朋友,你应该改进你的代码直到你没有它们)并且可能-g(成为能够使用-g 调试器)。出于基准测试目的,请编译器使用optimize(例如使用-O1-O2 -mcpu=native)。

注意-H preprocessor option:它要求gcc 显示每个包含的文件。有时(例如调试一些讨厌的宏)您想查看翻译单元的预处理形式,使用gcc -C -E 来获取它。

【讨论】:

  • 好的,我会考虑这个,现在编译。谢谢。
猜你喜欢
  • 2010-10-17
  • 1970-01-01
  • 1970-01-01
  • 2019-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多