2017-04-19 69 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發出警告。