1樓:匿名使用者
h檔案和c檔案本質上沒有任何區別。只不過一般.h檔案是標頭檔案,內含函式宣告、巨集定義、結構體定義等內容。.
c檔案是程式檔案,內含函式實現,變數定義等內容。而且是什麼字尾也沒有關係,只不過編譯器會預設對某些字尾的檔案採取某些動作。可以強制編譯器把任何字尾的檔案都當作c檔案來編。
在頭件中進行函式,變數宣告,巨集宣告,結構體宣告,而在c檔案中去進行變數定義,函式實現原因有四:
如果在標頭檔案中實現一個函式體,那麼如果在多個c檔案中引用它,而且又同時編譯多個c檔案,將其生成的目標檔案連線成一個可執行檔案,在每個引用此標頭檔案的c檔案所生成的目標檔案中,都有一份這個函式的**,如果這段函式又沒有定義成區域性函式,那麼在連線時,就會發現多個相同的函式,就會報錯。
如果在標頭檔案中定義全域性變數,並且將此全域性變數賦初值,那麼在多個引用此標頭檔案的c檔案中同樣存在相同變數名的拷貝,關鍵是此變數被賦了初值,所以編譯器就會將此變數放入data段,最終在連線階段,會在data段中存在多個相同的變數,它無法將這些變數統一成一個變數,也就是僅為此變數分配一個空間,而不是多份空間,假定這個變數在標頭檔案沒有賦初值,編譯器就會將之放入 bss段,聯結器會對bss段的多個同名變數僅分配一個儲存空間。
如果在c檔案中宣告巨集,結構體,函式等,那麼我要在另一個c檔案中引用相應的巨集,結構體,就必須再做一次重複的工作,如果改了一個c檔案中的一個宣告,那麼又忘了改其它c檔案中的宣告,這不就出了大問題了,程式的邏輯就變成了你不可想象的了,如果把這些公共的東東放在一個標頭檔案中,想用它的c檔案就只需要引用一個就ok了!這樣方便很多,要改某個宣告的時候,只需要動一下標頭檔案就行了。
在標頭檔案中宣告結構體,函式等,當需要將**封裝成一個庫,讓別人來用,又不想公佈原始碼,一種方法是公佈原始碼,別人想怎麼用就怎麼用,另一種是提供標頭檔案,別人從標頭檔案中看函式原型,這樣人家才知道如何呼叫你寫的函式。
2樓:**的可樂
main函式為標準c/c++的程式入口,編譯器會先找到該函式所在的檔案。
假定編譯程式編譯myproj.c(其中含main())時,發現它include了mylib.h(其中宣告瞭函式void test()),那麼此時編譯器將按照事先設定的路徑(include路徑列表及**檔案所在的路徑)查詢與之同名的實現檔案(副檔名為.
cpp或.c,此例中為mylib.c),如果找到該檔案,並在其中找到該函式(此例中為void test())的實現**,則繼續編譯;如果在指定目錄找不到實現檔案,或者在該檔案及後續的各include檔案中未找到實現**,則返回一個編譯錯誤。
其實include的過程完全可以「看成」是一個檔案拼接的過程,將宣告和實現分別寫在標頭檔案及c檔案中,或者將二者同時寫在標頭檔案中,理論上沒有本質的區別。
以上是所謂動態方式。
對於靜態方式,基本所有的c/c++編譯器都支援一種連結方式被稱為static link,即所謂靜態連結。在這種方式下,我們所要做的,就是寫出包含函式,類等等宣告的標頭檔案(a.h,b.
h,...),以及他們對應的實現檔案(a.cpp,b.
cpp,...),編譯程式會將其編譯為靜態的庫檔案(a.lib,b.
lib,...)。在隨後的**重用過程中,我們只需要提供相應的標頭檔案(.
h)和相應的庫檔案(.lib),就可以使用過去的**了。
相對動態方式而言,靜態方式的好處是實現**的隱蔽性,即c++中提倡的「介面對外,實現**不可見」。有利於庫檔案的**。
3樓:匿名使用者
在c語言家族程式中,標頭檔案被大量使用。一般而言,每個c++/c程式通常由標頭檔案(header files)和定義檔案(definition files)組成。標頭檔案作為一種包含功能函式、資料介面宣告的載體檔案,主要用於儲存程式的宣告(declaration),而定義檔案用於儲存程式的實現 (implementation)。
.c就是程式檔案。
(1)通過標頭檔案來呼叫庫功能。在很多場合,源**不便(或不準)向使用者公佈,只要向使用者提供標頭檔案和二進位制的庫即可。使用者只需要按照標頭檔案中的介面宣告來呼叫庫功能,而不必關心介面怎麼實現的。
編譯器會從庫中提取相應的**。
(2)標頭檔案能加強型別安全檢查。如果某個介面被實現或被使用時,其方式與標頭檔案中的宣告不一致,編譯器就會指出錯誤,這一簡單的規則能大大減輕程式設計師除錯、改錯的負擔。
預處理是編譯器的前驅,作用是把儲存在不同檔案裡的程式模組整合為一個完整的源程式.
#include本身只是一個簡單的檔案包含預處理命令,即為把include的後面檔案放到這條命令這裡,除此之外,沒有其它的用處(至少我也樣認為).
4樓:匿名使用者
c語言的標頭檔案字尾是什麼根本沒關係.只要檔名和include名一樣就行,即使沒字尾也能呼叫
5樓:匿名使用者
開始編譯的時候 編譯器首先會根據你的include extern define 等關鍵字將這些內容連結過來,然後才從main函式處進行編譯 你可以看看編譯規則方面的資料。
6樓:
根據你編譯方式的不同,實現這個特性的方法有動態和靜態之分。要講清楚的話不是太容易,要涉及到組合語言的知識,還要涉及到目標檔案的格式(win的pe,unix的elf)。
你還是自己去找書,或者上網查吧。關鍵字可以是「連結」「重定位」等等
7樓:匿名使用者
既然ccc.h有原型,而實現再ccc.c,那麼ccc.h裡得包括ccc.c把?
8樓:
其實這一切都有整合開發工具幫你做了。
如果用make命令來自己控制編譯過程,事情很明白了。
比如aaa.h 和 aaa.cpp 定義了函式 int test(void)
mian.cpp 含有對test函式的引用。
首先編譯每一個.cpp檔案,生成對應的.obj檔案。
在編譯的過程中對於呼叫的函式並不需要具體的實現,只要知道函式的原型即可,在函式呼叫的地方生成一個引用符號。
連結的時候需要找到引用符號的實現。
link main.obj aaa.obj 此時編譯器要在main.obj、aaa.obj中查詢test的實現。
如果只 link main.obj 此時編譯器會提示一個錯誤找不到test符號什麼的。
編譯和連結的過程由整合開發環境自動生成。
標註庫檔案只需要引用標頭檔案,連結的時候編譯器自動查詢對應的.lib
自己的庫,不但在原始碼中包含標頭檔案,在連結時還要指明庫檔案。
9樓:匿名使用者
好像不是很明白!~~
10樓:匿名使用者
看明白了,可樂說的很詳細了
c語言標頭檔案的位置,C語言標頭檔案的位置?
c語言中的標頭檔案一般分為兩類,一類是標準庫標頭檔案,一類是使用者自定義標頭檔案。1 標準庫標頭檔案,不同的編譯器都不相同。vc6.0一般在安裝目錄下的 vc98 include目錄,比如c program files x86 microsoft visual studio vc98 include...
c語言檔案中rb和r有什麼區別,C語言檔案中,「rb」和「r」有什麼區別?
一 作用不同 1 rb 代表二進位制檔案,用來讀寫二進位制檔案。二 特點不同 1 rb 檔案編碼是變長的,靈活利用率要高,而譯碼要難一些,不同的二進位制檔案譯碼方式是不同的。2 r 是一種典型的順序檔案,其檔案的邏輯結構又屬於流式檔案。三 優劣不同 1 rb 二進位制檔案比較節約空間,這兩者儲存字元...
C語言檔案指標,C語言中通過檔案指標訪問檔案有什麼好處?
你還沒解決嗎?你的bug應該不是檔案方式的問題。我才起來給你除錯,應該是 這一句的問題 fp1是檔案指標,fopen s函式返回的值型別是errno t 也就是int型別的值,因fp1錯誤的使用,而接受了fopen s函式的返回值,此時fp1指標的值變成0x0000000d fopen s函式的返回...