• <output id="aynwq"><form id="aynwq"><code id="aynwq"></code></form></output>

    <mark id="aynwq"><option id="aynwq"></option></mark>
  • <mark id="aynwq"><option id="aynwq"></option></mark><label id="aynwq"><dl id="aynwq"></dl></label>
  • 學習啦>知識大全>知識百科>百科知識>

    .c .h 文件的區別

    時間: 映芳735 分享

      C語言中有.c和.h文件這兩種文件格式代碼,那么它們之間有什么區別,下面小編講一講之間有什么區別。

      一、編譯器

      c文件與.h文件有什么不同之處,首先需要弄明白編譯器的工作過程,一般說來編譯器會做以下幾個過程:

      1.預處理階段

      2.詞法與語法分析階段

      3.編譯階段,首先編譯成純匯編語句,再將之匯編成跟CPU相關的二進制碼,生成各個目標文件

      4.連接階段,將各個目標文件中的各段代碼進行絕對地址定位,生成跟特定平臺相關的可執行文件,當然,最后還可以用objcopy生成純二進制碼,也就是去掉了文件格式信息。

      編譯器在編譯時是以c文件為單位進行的,也就是說如果你的項目中一個c文件都沒有,那么你的項目將無法編譯,連接器是以目標文件為單位,它將一個或多個目標文件進行函數與變量的重定位,生成最終的可執行文件,在PC上的程序開發,一般都有一個main函數,這是各個編譯器的約定,當然,你如果自己寫連接器腳本的話,可以不用main函數作為程序入口。

      二、c文件

      有了這些基礎知識,為了生成一個最終的可執行文件,就需要一些目標文件,也就是需要C文件,而這些C文件中又需要一個main函數作為可執行程序的入口,那么我們就從一個C文件入手,假定這個C文件內容如下:

      #include

      #include "mytest.h"

      int main(int argc,char **argv)

      {

      test = 25;

      printf("test.................%d\n",test);

      }

      三、h文件

      1,當一個函數要經常使用(比如有十幾個C文件使用它)時,一般我都放在H文件里,并在前面加上__inline.對于__inline函數,很多C文件都可以INCLUDE這個H文件,但是它好象只能被一個H文件INCLUDE,如果有兩個H文件INCLUDE它,就會出現編譯錯誤。

      2,有些數組變量,其大小可能達十幾K,而且要賦初值,這就不放在C文件里了,要不人都蒙了。

      3,

      #ifndef _feed_dog_h

      #define _feed_dog_h

      extern void feed_dog(void);

      #endif

      mohanwei兄,是不是這樣定議了,這個feed_dog.h就可以無數次的被INCLUDE了。

      四、編譯器的工作

      1.預處理階段:編譯器以C文件作為一個單元,首先讀這個C文件,發現第一句與第二句是包含.h文件,就會在所有搜索路徑中尋找這兩個文件,找到之后,就會將相應.h文件中再去處理宏,變量,函數聲明,嵌套的.h文件包含等,檢測依賴關系,進行宏替換,看是否有重復定義與聲明的情況發生,最后將那些文件中所有的東東全部掃描進這個當前的C文件中,形成一個中間“C文件”

      2.編譯階段,在上一步中相當于將那個.h文件中的test變量掃描進了一個中間C文件,那么test變量就變成了這個文件中的一個全局變量,此時,就將所有這個中間C文件的所有變量,函數分配空間,將各個函數編譯成二進制碼,按照特定目標文件格式生成目標文件,在這種格式的目標文件中進行各個全局變量,函數的符號描述,將這些二進制碼按照一定的標準組織成一個目標文件

      3.連接階段,將上一步成生的各個目標文件,根據一些參數,連接生成最終的可執行文件,主要的工作就是重定位各個目標文件的函數,變量等,相當于將個目標文件中的二進制碼按一定的規范合到一個文件中

      五、c文件與h文件區別

      理論上來說C文件與h文件里的內容,只要是C語言所支持的,無論寫什么都可以的,比如你在h文件中寫函數體,只要在任何一個C文件包含此.h文件就可以將這個函數編譯成目標文件的一部分(編譯是以C文件為單位的,如果不在任何C文件中包含此.h文件的話,這段代碼就形同虛設),你可以在C文件中進行函數聲明,變量聲明,結構體聲明,這也不成問題!!!那為何一定要分成h文件與C文件呢?又為何一般都在h文件中進行函數,變量聲明,宏聲明,結構體聲明呢?而在C文件中去進行變量定義,函數實現呢??原因如下:

      1.如果在h文件中實現一個函數體,那么如果在多個C文件中引用它,而且又同時編譯多個C文件,將其生成的目標文件連接成一個可執行文件,在每個引用此h文件的C文件所生成的目標文件中,都有一份這個函數的代碼,如果這段函數又沒有定義成局部函數,那么在連接時,就會發現多個相同的函數,就會報錯

      2.如果在h文件中定義全局變量,并且將此全局變量賦初值,那么在多個引用此h文件的C文件中同樣存在相同變量名的拷貝,關鍵是此變量被賦了初值,所以編譯器就會將此變量放入DATA段,最終在連接階段,會在DATA段中存在多個相同的變量,它無法將這些變量統一成一個變量,也就是僅為此變量分配一個空間,而不是多份空間,假定這個變量在h文件沒有賦初值,編譯器就會將之放入BSS段,連接器會對BSS段的多個同名變量僅分配一個存儲空間

      3.如果在C文件中聲明宏,結構體,函數等,那么我要在另一個C文件中引用相應的宏,結構體,就必須再做一次重復的工作,如果我改了一個C文件中的一個聲明,那么又忘了改其它C文件中的聲明,這不就出了大問題了,程序的邏輯就變成了你不可想象的了,如果把這些公共的東東放在一個頭文件中,想用它的C文件就只需要引用一個就OK了!!!這樣豈不方便,要改某個聲明的時候,只需要動一下h文件就行了

      4.在h文件中聲明結構體,函數等,當你需要將你的代碼封裝成一個庫,讓別人來用你的代碼,你又不想公布源碼,那么人家如何利用你的庫呢?也就是如何利用你的庫中的各個函數呢??一種方法是公布源碼,別人想怎么用就怎么用,另一種是提供頭文件,別人從頭文件中看你的函數原型,這樣人家才知道如何調用你寫的函數,就如同你調用printf函數一樣,里面的參數是怎樣的??你是怎么知道的??還不是看人家的頭文件中的相關聲明

    538487 主站蜘蛛池模板: 亚洲av综合色区无码专区桃色| 欧美性生恔XXXXXDDDD| 性色AV一区二区三区无码| 国产一级片网址| 久久久精品人妻一区二区三区| 青青国产成人久久激情911| 日韩中文字幕亚洲无线码| 国产午夜精品理论片| 亚洲精品视频在线播放| av2021天堂网手机版| 色综合五月婷婷| 新婚夜的娇吟声| 国产一二三区在线观看| 久久久久亚洲av无码尤物| 色综合中文字幕| 成品煮伊在2021一二三久| 国产一二三视频| 一本色综合久久| 男女午夜爽爽大片免费| 夜夜揉揉日日人人青青| 亚洲电影唐人社一区二区| 884aa四虎在线| 欧洲大片无需服务器| 国产在线观看一区二区三区| 久久国产成人精品| 色偷偷狠狠色综合网| 怡红院老首页主页入口| 伊人蕉久中文字幕无码专区| 91精品国产91久久久久久最新| 欧美成人精品福利在线视频| 国产熟女乱子视频正在播放| 久久精品视频网站| 色与欲影视天天看综合网| 成人av鲁丝片一区二区免费| 免费观看a级毛片| 91高清免费国产自产| 果冻传媒电影在线| 国产一区二区三区在线免费观看| 一本一本久久a久久精品综合麻豆| 渣男渣女抹胸渣男渣女| 国产真实乱对白精彩久久|