2017-04-19 158 views
3

有一个函数ffoo.c,我把f Prototypes纳入头文件关于C程序中的.c文件和.h文件?

,然后,有3个问题:

  1. 没有头文件必须命名为foo.h
  2. 确实foo.cfoo.h必须在同一个目录
  3. 如果两个问题的答案都是,也就是说,一个头文件可以命名为f.h,foo.cf.h可以在不同的目录下。看起来例如:

〜/的CFile/foo.c的

#include "~/hfile/f.h" 
int f(void){ 
    ... 
} 

〜/ HFILE/FH

int f(void); 

〜/主/ cmain.c

#include "~/hfile/f.h" 
int main(void){ 
    f(); 
    ... 
} 

然后,当我打电话f功能cmain.ccmain.c可以通过#include指令找到FH,但cmain.c如何找到foo.c的 FH,因为cmain.c只包括fh不包括foo.c?或者编译器或链接器如何找到foo.c by f.h

+0

为什么所有的downvotes所有正确的答案? –

+2

我在回答这个问题的时候,当我注意到所有的答案出现,并且有人对每个答案都给予-1s ...有些人只是为了好玩而做它,我猜... – Rogus

+0

@Anders - 有人可能会相信答案都是错误的,并相应地投票。 :-) –

回答

3

1.做头文件必须名为foo.h中?

这并不是必须的,但它可以方便,大部分时间是不成文的规则。

2.不foo.c的和foo.h中必须是在同一个目录?

这是没有必要的。你可以给c编译器包含目录。或者你可以包括相对于一个目录例如

#include "inc/foo.h" 

3.如果回答这两个问题是否定的,也就是说,一个头文件可以命名为f.h,foo.c的和f.h可以在不同的目录中。然后,当我调用f函数时,它可以通过#include指令找到f.h文件,但编译器或链接程序如何找到foo.c并从foo.c调用f?

查看答案。例如看到gcc手册与-I选项(https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html

更新: 由于议题扩大,也许你还可以看一个较早的帖子C/C++ header and implementation files: How do they work?

+0

我更新我的问题,你能再次看到吗? – Guo

2
  1. 没有,你能说出任何你喜欢
  2. 没有,你可以将头文件,无论你喜欢
  3. 如果头文件不放置在同一位置与源文件头文件您必须将头文件的位置交给编译器。如何为gcc做到这一点在这个问题的答案中有描述:How to include header files in GCC search path?
2

你可以为你的文件命名你想要的任何东西。只要你正确地告诉编译器和链接器这些文件的位置,你就可以把你的文件放在你喜欢的任何地方。你甚至不必以.c.h结尾的文件名 - 这些大多只是公约,但是很好。 我真的建议你去.c.h文件名结尾!

假设您调用一个文件foo.c并将其放入~/my-sources目录中。也可以说你打电话给另一个文件bar.header并把它放在~/my-headers目录中。然后你#include指令必须是这个样子:

#include "../my-headers/bar.header" 

此假设你是一个类UNIX系统上。您将不得不运用您所使用的操作系统知识来使#include指令正常工作。

因为头文件在编译时在源文件中包含包含,所以它实际上就像源文件中的头文件几乎完全一样。所以只要你告诉编译器在哪里找到你的文件(在编译时通过命令行,并且在你的#include指令中有正确的路径),你可以把你的文件放在任何地方。

+0

Downvoter,关心评论? –

+0

我更新我的问题,你能再次看到吗? – Guo

6

做头文件必须名为foo.h中?

不,但是使用将程序的相关部分联系在一起的名称(即使它是结构化的联系,而不是逻辑上的联系)是一件非常合理的事情。请记住,代码/源代码树适用于人类,而不是机器。

做的foo.c和foo.h中必须在同一目录

号但包括路径必须正确设置,以便foo.c作后盾。

但编译器或链接器如何找到foo.c并从foo.c调用f?

你必须对编译器/连接指定这些东西。咨询他们的文档。由于为大型项目做这件事可能有点令人生畏,甚至有些工具可以根据您指定的规则为您管理构建。一个典型的例子是make程序。


至于你添加的代码示例。仅仅包含头文件并不足以构建程序。标题只包含声明。您必须指示链接器获取相关的目标文件并将它们链接到一个可执行文件中。

认为,如果作为拼图。每个声明都凹陷在一个对象文件中,具有特定的形状。每个函数定义在特定形状的对象文件中碰撞。链接器的工作就像将拼图放在一起时一样,可以适应凹痕。

+0

我更新了我的问题,你能再次看到吗? – Guo

+0

@郭 - 你可以不要添加更多的问题,已经回答的职位?它使现有的答案无效,并且是非常差的SO网络礼节。另外,你问的所有内容都由我最后一段回答。 – StoryTeller

+0

当我需要更新问题时,我该做什么? – Guo

2
  1. 没有
  2. 没有
  3. 当你想编译输出(可以是一个过程或静态/动态库),你给编译器的源文件(在你的情况foo.c),然后它会搜索所有这些源文件以查找函数的定义。
2
  1. 做头文件必须名为foo.h中?

NO。

  • 确实的foo.c和foo.h中必须是在同一目录中?
  • NO。

  • 如果回答两个问题是否定的,也就是说,一个头文件 可以命名f.h,foo.c的和f.h可以在不同的目录中。然后,当我 调用F功能,它可以找到#include指令f.h文件,但如何 编译器或链接找到的foo.c和foo.c的调用F?
  • 这取决于你。如果你把标题f.h和源文件foo.c同一目录,则只需添加一个头文件到foo.c文件,如:

    #include "f.h" 
    

    但是,如果你把标题f.h和源文件foo.c不同目录,然后添加头文件的路径成foo.c,如:

    #include "Your_header_file_Path/f.h" 
    
    +0

    我更新我的问题,你能再次看到吗? – Guo

    1
    #include

    literally inserts引用的文件它在哪里使用。

    ,如果你想知道最终是给编译器什么查看preprocessor中间。

    链接器的工作方式不同,它只是包含所有对象的列表。如果对象在那里,它可以找到它。
    如果您没有正确引用它,它会以某种形式implicit declaration发出警告。