操屁眼的视频在线免费看,日本在线综合一区二区,久久在线观看免费视频,欧美日韩精品久久综

新聞資訊

    原則2:頭文件應當職責單一。

    說明:頭文件過于復雜,依賴過于復雜是導致編譯時間過長的主要原因。很多現有代碼中頭文件過大,職責過多, 再加上循環依賴的問題,可能導致為了在.c中使用一個宏,而包含十幾個頭文件。

    某個頭文件不但定義了基本數據類型WORD,還包含了stdio.h .h等等不常用的頭文件。

    如果工程中有10000個源文件,而其中100個源文件使用了stdio.h的數據結構頭文件和源文件,由于上述頭文件的職責過于龐大,而WORD又是每一個文件必須包含的,從而導致stdio.h/.h等可能被不必要的展開了9900次,大大增加了工程的編譯時間。

    原則3:頭文件應向穩定的方向包含。

    說明:頭文件的包含關系是一種依賴,一般來說數據結構頭文件和源文件,應當讓不穩定的模塊依賴穩定的模塊,從而當不穩定的模塊發生變化時,不會影響(編譯)穩定的模塊。

    就我們的產品來說,依賴的方向應該是:產品依賴于平臺,平臺依賴于標準庫。某產品線平臺的代碼中已經包含了產品的頭文件,導致平臺無法單獨編譯、發布和測試, 是一個非常糟糕的反例。

    除了不穩定的模塊依賴于穩定的模塊外,更好的方式是兩個模塊共同依賴于接口,這樣任何一個模塊的內部實現更改都不需要重新編譯另外一個模塊。在這里,我們假設接口本身是最穩定的。

    延伸閱讀材料:編者推薦開發人員使用“依賴倒置”原則,即由使用者制定接口,服務提供者實現接口,更具體的描述可以參見《 敏捷軟件開發:原則、模式與實踐》 ( C. 著 鄧輝 譯 清華大學出版社2003年9月) 的第二部分“敏捷設計”章節。

    規則1:每一個.c文件應有一個同名.h文件,用于聲明需要對外公開的接口。

    說明:如果一個.c文件不需要對外公布任何接口,則其就不應當存在,除非它是程序的入口,如main函數所在的文件。

    現有某些產品中,習慣一個.c文件對應兩個頭文件,一個用于存放對外公開的接口,一個用于存放內部需要用到的定義、聲明等,以控制.c文件的代碼行數。編者不提倡這種風格。

    這種風格的根源在于源文件過大,應首先考慮拆分.c文件,使之不至于太大。另外,一旦把私有定義、聲明放到獨立的頭文件中,就無法從技術上避免別人之,難以保證這些定義最后真的只是私有的。

    本規則反過來并不一定成立。有些特別簡單的頭文件,如命令ID定義頭文件,不需要有對應的.c存在[a1] 。

    示例:對于如下場景,如在一個.c中存在函數調用關系:

    void?foo()
    {
    ?bar();
    }

    void?bar()
    {
    ?Do?something;
    }

    必須在foo之前聲明bar,否則會導致編譯錯誤。

    這一類的函數聲明,應當在.c的頭部聲明,并聲明為的,如下:

    static?void?bar();

    void?foo()
    {
    ?bar();
    }

    void?bar()
    {
    ?Do?something;
    }

    規則2:禁止頭文件循環依賴。

    說明:頭文件循環依賴,指a.h包含b.h, b.h包含c.h, c.h包含a.h之類導致任何一個頭文件修改,都導致所有包含了a.h/b.h/c.h的代碼全部重新編譯一遍。

    而如果是單向依賴,如a.h包含b.h, b.h包含c.h,而c.h不包含任何頭文件,則修改a.h不會導致包含了b.h/c.h的源代碼重新編譯。

    規則3:.c/.h文件禁止包含用不到的頭文件。

    說明:很多系統中頭文件包含關系復雜,開發人員為了省事起見,可能不會去一一鉆研,直接包含一切想到的頭文件,甚至有些產品干脆發布了一個god.h,其中包含了所有頭文件,然后發布給各個項目組使用,這種只圖一時省事的做法,導致整個系統的編譯時間進一步惡化,并對后來人的維護造成了巨大的麻煩。

    規則4:頭文件應當自包含。

    說明:簡單的說,自包含就是任意一個頭文件均可獨立編譯。如果一個頭文件包含某個頭文件,還要包含另外一個頭文件才能工作的話,就會增加交流障礙,給這個頭文件的用戶增添不必要的負擔[a2] 。

    示例:如果a.h不是自包含的,需要包含b.h才能編譯,會帶來的危害:每個使用a.h頭文件的.c文件,為了讓引入的a.h的內容編譯通過,都要包含額外的頭文件b.h。額外的頭文件b.h必須在a.h之前進行包含,這在包含順序上產生了依賴。

    注意:該規則需要與“ .c/.h文件禁止包含用不到的頭文件”規則一起使用,不能為了讓a.h自包含,而在a.h中包含不必要的頭文件。a.h要剛剛可以自包含,不能在a.h中多包含任何滿足自包含之外的其他頭文件。

    規則5:總是編寫內部#保護符( # 保護)。

    說明:多次包含一個頭文件可以通過認真的設計來避免。如果不能做到這一點,就需要采取阻止頭文件內容被包含多于一次的機制。

    通常的手段是為每個文件配置一個宏,當頭文件第一次被包含時就定義這個宏,并在頭文件被再次包含時使用它以排除文件內容。

    所有頭文件都應當使用# 防止頭文件被多重包含,命名格式為,為了保證唯一性,更好的命名是。

    注:沒有在宏最前面加上““,即使用代替,是因為一般以”“和”“開頭的標識符為系統保留或者標準庫使用,在有些靜態檢查工具中,若全局可見的標識符以””開頭會給出告警。

    定義包含保護符時,應該遵守如下規則:

    1)保護符使用唯一名稱;

    2)不要在受保護部分的前后放置代碼或者注釋。

    示例:假定VOS工程的timer模塊的timer.h,其目錄為VOS//timer/timer.h,應按如下方式保護:

    #ifndef?VOS_INCLUDE_TIMER_TIMER_H

    #define?VOS_INCLUDE_TIMER_TIMER_H

    ...

    #endif

    也可以使用如下簡單方式保護:

    #ifndef?TIMER_H

    #define?TIMER_H

    ..

    #endif

    例外情況:頭文件的版權聲明部分以及頭文件的整體注釋部分(如闡述此頭文件的開發背景、使用注意事項等)可以放在保護符(# XX_H)前面。

    規則6:禁止在頭文件中定義變量。

    說明:在頭文件中定義變量,將會由于頭文件被其他.c文件包含而導致變量重復定義。

    規則7:只能通過包含頭文件的方式使用其他.c提供的接口,禁止在.c中通過的方式使用外部函數接口、變量[a3] 。

    說明:若a.c使用了b.c定義的foo()函數,則應當在b.h中聲明 int foo(int input);并在a.c中通過# 來使用foo。

    禁止通過在a.c中直接寫 int foo(int input);來使用foo,后面這種寫法容易在foo改變時可能導致聲明和定義不一致[a4] 。

    規則8:禁止在 “C”中包含頭文件。

    說明:在 “C”中包含頭文件, 會導致 “C”嵌套, 對 “C”嵌套層次有限制,嵌套層次太多會編譯錯誤。

    在 “C”中包含頭文件,可能會導致被包含頭文件的原有意圖遭到破壞。例如,存在a.h和b.h兩個頭文件:

    使用C++預處理器展開b.h,將會得到

    extern?"C"
    {
    ??void?foo(int);
    ??void?b();
    }

    按照a.h作者的本意,函數foo是一個C++自由函數,其鏈接規范為”C++”。但在b.h中,由于# “a.h”被放到了 “C” { }的內部,函數foo的鏈接規范被不正確地更改了。

    示例:錯誤的使用方式:

    extern?"C"
    {
    ??#include?"xxx.h"
    ??...
    }

    正確的使用方式:

    #include?"xxx.h"

    extern?"C"
    {
    ??...
    }

    建議1:一個模塊通常包含多個.c文件,建議放在同一個目錄下,目錄名即為模塊名。為方便外部使用者,建議每一個模塊提供一個.h,文件名為目錄名。

    說明:需要注意的是,這個.h并不是簡單的包含所有內部的.h,它是為了模塊使用者的方便,對外整體提供的模塊接口。

    以 test(簡稱GTest)為例, GTest作為一個整體對外提供C++單元測試框架,其1.5版本的gtest工程下有6個源文件和12個頭文件。

    但是它對外只提供一個gtest.h,只要包含gtest.h即可使用GTest提供的所有對外提供的功能,使用者不必關系GTest內部各個文件的關系,即使以后GTest的內部實現改變了,比如把一個源文件c拆成兩個源文件,使用者也不必關心,甚至如果對外功能不變,連重新編譯都不需要。

    對于有些模塊,其內部功能相對松散,可能并不一定需要提供這個.h,而是直接提供各個子模塊或者.c的頭文件。

    比如產品普遍使用的VOS,作為一個大模塊,其內部有很多子模塊,他們之間的關系相對比較松散,就不適合提供一個vos.h。而VOS的子模塊,如(僅作舉例說明,與實際情況可能有所出入),其內部實現高度內聚,雖然其內部實現可能有多個.c和.h,但是對外只需要提供一個.h聲明接口。

    建議2:如果一個模塊包含多個子模塊,則建議每一個子模塊提供一個對外的.h,文件名為子模塊名。

    說明:降低接口使用者的編寫難度。

    建議3:頭文件不要使用非習慣用法的擴展名,如.inc。

    說明:目前很多產品中使用了.inc作為頭文件擴展名,這不符合c語言的習慣用法。在使用.inc作為頭文件擴展名的產品,習慣上用于標識此頭文件為私有頭文件。

    但是從產品的實際代碼來看,這一條并沒有被遵守,一個.inc文件被多個.c包含比比皆是。本規范不提倡將私有定義單獨放在頭文件中,具體見 規則1.1。

    除此之外,使用.inc還導致 、 等IDE工具無法識別其為頭文件,導致很多功能不可用,如“跳轉到變量定義處”。

    雖然可以通過配置,強迫IDE識別.inc為頭文件,但是有些軟件無法配置,如 只能識別.h而無法通過配置識別.inc。

    建議4:同一產品統一包含頭文件排列方式。

    說明:常見的包含頭文件排列方式:功能塊排序、文件名升序、穩定度排序。

    以穩定度排序,建議將不穩定的頭文件放在前面,如把產品的頭文件放在平臺的頭文件前面,如下:

    相對來說, .h修改的較為頻繁,如果有錯誤,不必編譯.h就可以發現.h的錯誤,可以部分減少編譯時間。

    [a1] 例如一些屏驅動的地址文件,一些協議的格式定義文件.只存在.c或者.h即可,不一定兩者都要有。

    [a2] 我對自包含沒有太理解,只是明白在.h文件里盡量不包含沒有必要的頭文件,某些情況下不得已才進行包含其它頭文件的操作。

    [a3] 這種做法我寫代碼常用,但后面應該盡量避免,而是通過調用頭文件的方式來使用該函數。

    [a4] 對,我就遇到過。因為隨著工程量的增大,后面某個細節調整了foo函數,但其它調用它的地方沒有及時改正,而KEIL編譯器又沒有報錯,導致bug出現,而且不易查找。

網站首頁   |    關于我們   |    公司新聞   |    產品方案   |    用戶案例   |    售后服務   |    合作伙伴   |    人才招聘   |   

友情鏈接: 餐飲加盟

地址:北京市海淀區    電話:010-     郵箱:@126.com

備案號:冀ICP備2024067069號-3 北京科技有限公司版權所有