欧美大屁股bbbbxxxx,狼人大香伊蕉国产www亚洲,男ji大巴进入女人的视频小说,男人把ji大巴放进女人免费视频,免费情侣作爱视频

歡迎來到入門教程網(wǎng)!

C語言

當(dāng)前位置:主頁 > 軟件編程 > C語言 >

Recommended C Style and Coding Standards中文翻譯版第1/3頁

來源:本站原創(chuàng)|時間:2020-01-10|欄目:C語言|點擊: 次

0. 摘要

本文翻譯自《Recommended C Style and Coding Standards》。

作者信息:

L.W. Cannon (Bell Labs)
R.A. Elliott (Bell Labs)
L.W. Kirchhoff (Bell Labs)
J.H. Miller (Bell Labs)
J.M. Milner (Bell Labs)
R.W. Mitze (Bell Labs)
E.P. Schan (Bell Labs)
N.O. Whittington (Bell Labs)
Henry Spencer (Zoology Computer Systems, University of Toronto)
David Keppel (EECS, UC Berkeley, CS&E, University of Washington)
Mark Brader (SoftQuad? Incorporated, Toronto)

本文是《Indian Hill C Style and Coding Standards》的更新版本,上面提到的最后三位作者對其進行了修改。本文主要介紹了一種C程序的推薦編碼標(biāo)準,內(nèi)容著重于講述編碼風(fēng)格,而不是功能 組織(Functional Organization)。


1. 簡介

本文檔修改于AT&T Indian Hill實驗室內(nèi)部成立的一個委員會的一份文檔,旨在于建立一套通用的編碼標(biāo)準并推薦給Indian Hill社區(qū)。

本文主要講述編碼風(fēng)格。良好的風(fēng)格能夠鼓勵大家形成一致的代碼布局,提高代碼可移植性并且減少錯誤數(shù)量。

本文不關(guān)注功能組織,或是一些諸如如何使用goto的一般話題。我們嘗試將之前的有關(guān)C代碼風(fēng)格的文檔整合到一套統(tǒng)一的標(biāo)準中,這套標(biāo)準將適合于 任何使用C語言的工程,當(dāng)然還是會有部分內(nèi)容是針對一些特定系統(tǒng)的。另外不可避免地是這些標(biāo)準仍然無法覆蓋到所有情況。經(jīng)驗以及廣泛的評價十分重 要,遇到特殊情況時,大家應(yīng)該咨詢有經(jīng)驗的C程序員,或者查看那些經(jīng)驗豐富的C程序員們的代碼(最好遵循這些規(guī)則)。

本文中的標(biāo)準本身并不是必需的,但個別機構(gòu)或團體可能部分或全部采用該標(biāo)準作為程序驗收的一部分。因此,在你的機構(gòu)中其他人很可能以一種相似的風(fēng) 格編碼。最終,這些標(biāo)準的目的是提高可移植性,減少維護工作,尤其是提高代碼的清晰度。

這里很多風(fēng)格的選擇都有些許武斷?;旌系木幋a風(fēng)格比糟糕的編碼風(fēng)格更難于維護,所以當(dāng)變更現(xiàn)有代碼時,最好是保持與現(xiàn)有代碼風(fēng)格一致,而不是盲目 地遵循本文檔中的規(guī)則。

"清晰的是專業(yè)的;不清晰的則是外行的" — Sir Ernest Gowers

2. 文件組織

一個文件包含的各個部分應(yīng)該用若干個空行分隔。雖然對源文件沒有最大長度限制,但超過1000行的文件處理起來非常不方便。編輯器很可能沒有足夠 的臨時空間來編輯這個文件,編譯過程也會因此變得十分緩慢。與回滾到前面所花費的時間相比,那些僅僅呈現(xiàn)了極少量信息的多行星號是不值得的,我們 不鼓勵使用。超過79列的行無法被所有的終端都很好地處理,應(yīng)該盡可能的避免使用。過長的行會導(dǎo)致過深的縮進,這常常是一種代碼組織不善的癥狀。

2.1 文件命名慣例

文件名由一個基礎(chǔ)名、一個可選的句號以及后綴組成。名字的第一個字符應(yīng)該是一個字母,并且所有字符(除了句號)都應(yīng)該是小寫的字母和數(shù)字?;A(chǔ)名 應(yīng)該由八個或更少的字符組成,后綴應(yīng)該由三個或更少的字符組成(四個,如果你包含句號的話)。這些規(guī)則對程序文件以及程序使用和產(chǎn)生的默認文件都 適用(例如,"rogue.sav")。

一些編譯器和工具要求文件名符合特定的后綴命名約定。下面是后綴命名要求:

    C源文件的名字必須以.c結(jié)尾
    匯編源文件的名字必須以.s結(jié)尾

我們普遍遵循以下命名約定:

    可重定位目標(biāo)文件名以.o結(jié)尾
    頭文件名以.h結(jié)尾
        在多語言環(huán)境中一個可供選擇的更好的約定是用語言類型和.h共同作為后綴(例如,"foo.c.h" 或 "foo.ch")。

    Yacc源文件名以.y結(jié)尾
    Lex源文件名以.l結(jié)尾

C++使用編譯器相關(guān)的后綴約定,包括.c,..c,.cc,.c.c以及.C。由于大多C代碼也是C++代碼,因此這里并沒有一個明確的方案。

此外,我們一般約定使用"Makefile"(而不是"makefile")作為make(對于那些支持make的系統(tǒng))工具的控制文件,并且使 用"README"作為簡要描述目錄內(nèi)容或目錄樹的文件。


2.2 程序文件

下面是一個程序文件各個組成部分的推薦排列順序:

文件的第一部分是一個序,用于說明該文件中的內(nèi)容是什么。對文件中的對象(無論它們是函數(shù),外部數(shù)據(jù)聲明或定義,或是其他一些東西)用途的描述比 一個對象名字列表更加有用。這個序可選擇地包含作者信息、修訂控制信息以及參考資料等。

接下來是所有被包含的頭文件。如果某個頭文件被包含的理由不是那么顯而易見,我們需要通過增加注釋說明原因。大多數(shù)情況下,類似stdio.h這 樣的系統(tǒng)頭文件應(yīng)該被放在用戶自定義頭文件的前面。

接下來是那些用于該文件的defines和typedefs。一個常規(guī)的順序是先寫常量宏、再寫函數(shù)宏,最后是typedefs和枚舉 (enums)定義。

接下來是全局(外部)數(shù)據(jù)聲明,通常的順序如下:外部變量,非靜態(tài)(non-static)全局變量,靜態(tài)全局變量。如果一組定義被用于部分特定 全局數(shù)據(jù)(如一個標(biāo)志字),那么這些定義應(yīng)該被放在對應(yīng)數(shù)據(jù)聲明后或嵌入到結(jié)構(gòu)體聲明中,并將這些定義縮進到其應(yīng)用的聲明的第一個關(guān)鍵字的下一個 層次(譯注:實在沒有搞懂后面這句的含義)。

最后是函數(shù),函數(shù)應(yīng)該以一種有意義的順序排列。相似的函數(shù)應(yīng)該放在一起。與深度優(yōu)先(函數(shù)定義盡可能在他們的調(diào)用者前后)相比,我們應(yīng)該首選廣度 優(yōu)先方法(抽象層次相似的函數(shù)放在一起)。這里需要相當(dāng)多的判斷。如果定義大量本質(zhì)上無關(guān)的工具函數(shù),可考慮按字母表順序排列。

2.3 頭文件

頭文件是那些在編譯之前由C預(yù)處理器包含在其他文件中的文件。諸如stdio.h的一些頭文件被定義在系統(tǒng)級別,所有使用標(biāo)準I/O庫的程序必須 包含它們。頭文件還用來包含數(shù)據(jù)聲明和定義,這些數(shù)據(jù)不止一個程序需要。頭文件應(yīng)該按照功能組織,例如,獨立子系統(tǒng)的聲明應(yīng)該放到獨立的頭文件 中。如果一組聲明在代碼從一種機器移植到另外一種機器時變動的可能性很大,那么這些聲明也應(yīng)該被放在獨立的頭文件中。

避免私有頭文件的名字與標(biāo)準庫頭文件的名字一樣。下面語句:

復(fù)制代碼 代碼如下:
#include "math.h"

當(dāng)預(yù)期的頭文件在當(dāng)前目錄下沒有找到時,它將會包含標(biāo)準庫中的math頭文件。如果這的確是你所期望發(fā)生的,那么請加上注釋。包含頭文件時不要使 用絕對路徑。當(dāng)從標(biāo)準位置獲取頭文件時,請使用<name>包含頭文件;或相對于當(dāng)前路徑定義它們。C編譯器的"include- path"選項(在許多系統(tǒng)中為-l)是處理擴展私有庫頭文件的最好方法,它允許在不改變源碼文件的情況下重新組織目錄結(jié)構(gòu)。

聲明了函數(shù)或外部變量的頭文件應(yīng)該被那些定義了這些函數(shù)和變量的文件所包含。這樣一來,編譯器就可以做類型檢查了,并且外部聲明將總是與定義保持 一致。

在頭文件中定義變量往往是個糟糕的想法,它經(jīng)常是一個在文件間對代碼進行低劣劃分的癥狀。此外,在一次編譯中,像typedef和經(jīng)過初始化的數(shù) 據(jù)定義無法被編譯器看到兩次。在一些系統(tǒng)中,重復(fù)的沒有使用extern關(guān)鍵字修飾的未初始化定義也會導(dǎo)致問題。當(dāng)頭文件嵌套時,會出現(xiàn)重復(fù)的聲 明,這將導(dǎo)致編譯失敗。

頭文件不應(yīng)該嵌套。一個頭文件的序應(yīng)該描述其使用的其他被包含的頭文件的實用特性。在極特殊情況下,當(dāng)大量頭文件需要被包含在多個不同的源文件中 時,可以被接受的做法是將公共的頭文件包含在一個單獨的頭文件中。

一個通用的做法是將下面這段代碼加入到每個頭文件中以防止頭文件被意外多次包含。

復(fù)制代碼 代碼如下:

#ifndef EXAMPLE_H
#define EXAMPLE_H
 …    /* body of example.h file */
#endif /* EXAMPLE_H */

我們不應(yīng)該對這種避免多次包含的機制產(chǎn)生依賴,特別是不應(yīng)該因此而嵌套包含頭文件。

2.4 其他文件

還有一個慣例就是編寫一個名為"README"的文件,用于描述程序的整體情況以及問題。例如,我們經(jīng)常在README包含程序所使用的條件編譯 選項列表以及相關(guān)說明,還可以包含機器無關(guān)的文件列表等。

3. 注釋

"當(dāng)代碼與注釋不一致時,兩者很可能都是錯的" -- Norm Schryer

注釋應(yīng)該描述發(fā)生了什么,如何做的,參數(shù)的含義,使用和修改了哪些全局變量以及約束或Bugs。避免給那些本身很清晰的代碼加注釋,因為這些注釋信息將很快的過時。注釋與代碼不一致將會帶來負面影響。短小的注釋應(yīng)該是關(guān)于做什么的,比如"計算有意義的值",而不是關(guān)于"怎么做"的,例如"值的總和除以n"。C不是匯編;在頭3-10行的區(qū)域添加注釋,說明代碼總體是做什么的,經(jīng)常要比為每行添加注釋說明微邏輯更加有用。

注釋應(yīng)該為那些令人不悅的代碼作出"辯護"。辯護應(yīng)該是這樣的:如果使用正常的代碼,一些糟糕的事情將會發(fā)生。但僅僅讓代碼運行的更快還不足以讓這些hack代碼顯得合理化;而是應(yīng)該將那些在不使用hack代碼時令人無法接受的性能數(shù)據(jù)展示出來。注釋應(yīng)該對著寫不可接受的行為作出解釋,并告訴大家為什么使用Hack代碼可以很好的解決這個問題。

那些用于描述數(shù)據(jù)結(jié)構(gòu),算法等的注釋應(yīng)該以塊注釋的形式存在。塊注釋起始以/*占據(jù)1-2列,*放在每行注釋前面的第二列,塊注釋最后以占據(jù)2-3列的*/結(jié)尾。另外一個候選方案是每行注釋文字前面用*占據(jù)1-2列,塊注釋以占據(jù)1-2列的*/收尾。

復(fù)制代碼 代碼如下:

/*
 *    Here is a block comment.
 *    The comment text should be tabbed or spaced over uniformly.
 *    The opening slash-star and closing star-slash are alone on a line.
 */

/*
** Alternate format for block comments
*/


注意
復(fù)制代碼 代碼如下:

grep '^.\e*'

將匹配文件中所有的注釋。特別長的塊注釋,諸如持久討論或版權(quán)聲明,經(jīng)常以占據(jù)1-2列的/*開始,每行注釋文字前沒有*,并最終以占據(jù)1-2列的*/結(jié)束。函數(shù)內(nèi)部很適合使用塊注釋,塊注釋應(yīng)該與其描述的代碼擁有相同的縮進。獨立的單行注釋也應(yīng)該與其說明的代碼縮進一致。

復(fù)制代碼 代碼如下:

if (argc > 1) {
    /* Get input file from command line. */
    if (freopen(argv[1], "r", stdin) == NULL) {
        perror (argv[1]);
    }
}

特別短的注釋可以與其描述的代碼放在同一行上,并且要通過tab與代碼語句分隔開來。如果針對一塊代碼有不止一個短注釋,這些注釋應(yīng)該具有相同的縮進。
復(fù)制代碼 代碼如下:

if (a == EXCEPTION) {
    b = TRUE;                /* special case */
} else {
    b = isprime(a);            /* works only for odd a */
}

4. 聲明

全局聲明應(yīng)該從第一列開始。在所有外部數(shù)據(jù)聲明的前面都應(yīng)該放置extern關(guān)鍵字。如果一個外部變量是一個在定義時大小確定的數(shù)組,那么這個數(shù) 組界限必須在extern聲明時顯示指出,除非數(shù)組的大小與數(shù)組本身編碼在一起了(例如,一個總是以0結(jié)尾的只讀字符數(shù)組)。重復(fù)聲明數(shù)組大小對 于一些使用他人編寫的代碼的人特別有益。

指針修飾符*應(yīng)該與變量名在一起,而不是與類型在一起。

復(fù)制代碼 代碼如下:
char  *s, *t, *u;

替換

復(fù)制代碼 代碼如下:
char*  s, t, u;

后者是錯誤的,因為實際上t和u并未如預(yù)期那樣被聲明為指針。

不相關(guān)的聲明,即使是相同類型的,也應(yīng)該獨立占據(jù)一行。我們應(yīng)該對聲明對象的角色進行注釋,不過當(dāng)常量名本身足以說明角色時,使用#define 定義的常量列表則不需要注釋。通常多行變量名、值與注釋使用相同縮進,使得他們在一列直線上。盡量使用Tab字符而不是空格。結(jié)構(gòu)體和聯(lián)合體的聲 明時,每個元素應(yīng)該單獨占據(jù)一行,并附帶一條注釋。{應(yīng)該與結(jié)構(gòu)體的tag名放在同一行,}應(yīng)該放在聲明結(jié)尾的第一列。

復(fù)制代碼 代碼如下:

struct boat {
    int    wllength;    /* water line length in meters */
    int    type;        /* see below */
    long   sailarea;    /* sail area in square mm */
};

/* defines for boat.type */
#define    KETCH    (1)
#define    YAWL     (2)
#define    SLOOP    (3)
#define    SQRIG    (4)
#define    MOTOR    (5)


這些defines有時放在結(jié)構(gòu)體內(nèi)type聲明的后面,并使用足夠的tab縮進到結(jié)構(gòu)體成員成員的下一級。如果這些實際值不那么重要的話,使用 enum會更好。
復(fù)制代碼 代碼如下:

enum bt { KETCH=1, YAWL, SLOOP, SQRIG, MOTOR };
struct boat {
    int     wllength;    /* water line length in meters */
    enum bt type;        /* what kind of boat */
    long    sailarea;    /* sail area in square mm */
};

任何初值重要的變量都應(yīng)該被顯式地初始化,或者至少應(yīng)該添加注釋,說明依賴C的默認初始值0??粘跏蓟?{}"應(yīng)該永遠不被使用。結(jié)構(gòu)體初始化應(yīng) 該用大括號完全括起來。用于初始化長整型(long)的常量應(yīng)該使用顯式長度。使用大寫字母,例如2l看起來更像21,數(shù)字二十一。
復(fù)制代碼 代碼如下:

int   x = 1;
char  *msg = "message";
struct boat    winner[] = {
    { 40, YAWL, 6000000L },
    { 28, MOTOR, 0L },
    { 0 },
};

如果一個文件不是獨立程序,而是某個工程整體的一部分,那么我們應(yīng)該最大化的利用static關(guān)鍵字,使得函數(shù)和變量對于單個文件來說是局部范疇 的。只有在有清晰需求且無法通過其他方式實現(xiàn)的特殊情況時,我們才允許變量被其他文件訪問。這種情況下應(yīng)該使用注釋明確告知使用了其他文件中的變 量;注釋應(yīng)該說明其他文件的名字。如果你的調(diào)試器遮蔽了你需要在調(diào)試階段查看的靜態(tài)對象,那么可以將這些變量聲明為STATIC,并根據(jù)需要決定 是否#define STATIC。

最重要的類型應(yīng)該被typedef,即使他們只是整型,因為獨立的名字使得程序更加易讀(如果只有很少的幾個integer的typedef)。 結(jié)構(gòu)體在聲明時應(yīng)該被typedef。保持結(jié)構(gòu)體標(biāo)志的名字與typedef后的名字相同。

復(fù)制代碼 代碼如下:

typedef struct splodge_t {
    int  sp_count;
    char *sp_name, *sp_alias;
} splodge_t;

總是聲明函數(shù)的返回類型。如果函數(shù)原型可用,那就使用它。一個常見的錯誤就是忽略那些返回double的外部數(shù)學(xué)函數(shù)聲明。那樣的話,編譯器就會 假定這些函數(shù)的返回值為一個整型數(shù),并且將bit位逐一盡職盡責(zé)的注意轉(zhuǎn)換為一個浮點數(shù)(無意義)。

"C語言的觀點之一是程序員永遠是對的" — Michael DeCorte

5. 函數(shù)聲明

每個函數(shù)前面應(yīng)該放置一段塊注釋,概要描述該函數(shù)做什么以及(如果不是很清晰)如何使用該函數(shù)。重要的設(shè)計決策討論以及副作用說明也適合放在注釋 中。避免提供那些代碼本身可以清晰提供的信息。

函數(shù)的返回類型應(yīng)該單獨占據(jù)一行,(可選的)縮進一個級別。不用使用默認返回類型int;如果函數(shù)沒有返回值,那么將返回類型聲明為void。如 果返回值需要大段詳細的說明,可以在函數(shù)之前的注釋中描述;否則可以在同一行中對返回類型進行注釋。函數(shù)名(以及形式參數(shù)列表)應(yīng)該被單獨放在一 行,從第一列開始。目的(返回值)參數(shù)一般放在第一個參數(shù)位置(從左面開始)。所有形式參數(shù)聲明、局部聲明以及函數(shù)體中的代碼都應(yīng)該縮進一級。函 數(shù)體的開始括號應(yīng)該單獨一行,放在開始處的第一列。

每個參數(shù)都應(yīng)該被聲明(不要使用默認類型int)。通常函數(shù)中每個變量的角色都應(yīng)該被描述清楚,我們可以在函數(shù)注釋中描述,或如果每個聲明單獨一 行,我們可以將注釋放在同一行上。像循環(huán)計數(shù)器"i",字符串指針"s"以及用于標(biāo)識字符的整數(shù)類型"c"這些簡單變量都無需注釋。如果一組函數(shù) 都擁有一個相似的參數(shù)或局部變量,那么在所有函數(shù)中使用同一個名字來標(biāo)識這個變量是很有益處的(相反,避免在相關(guān)函數(shù)中使用一個名字標(biāo)識用途不同 的變量)。不同函數(shù)中的相似參數(shù)還應(yīng)該放在各個參數(shù)列表中的相同位置。

參數(shù)和局部變量的注釋應(yīng)該統(tǒng)一縮進以排成一列。局部變量聲明應(yīng)用一個空行與函數(shù)語句分隔開來。

當(dāng)你使用或聲明變長參數(shù)的函數(shù)時要小心。目前在C中尚沒有真正可移植的方式處理變長參數(shù)。最好設(shè)計一個使用固定個數(shù)參數(shù)的接口。如果一定要使用變 長參數(shù),請使用標(biāo)準庫中的宏來聲明具有變長參數(shù)的函數(shù)。

如果函數(shù)使用了在文件中沒有進行全局聲明的外部變量(或函數(shù)),我們應(yīng)該在函數(shù)體內(nèi)部使用extern關(guān)鍵字單獨對這些變量進行聲明。

避免局部聲明覆蓋高級別的聲明。尤其是,局部變量不應(yīng)該在嵌套代碼塊中被重聲明。雖然這在C中是合法的,但是當(dāng)使用-h選項時,潛在的沖突可能性 足以讓lint工具發(fā)出抱怨之聲。

123下一頁閱讀全文

上一篇:c++中引用和指針的區(qū)別和聯(lián)系

欄    目:C語言

下一篇:二叉搜索樹源碼分享

本文標(biāo)題:Recommended C Style and Coding Standards中文翻譯版第1/3頁

本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/3685.html

網(wǎng)頁制作CMS教程網(wǎng)絡(luò)編程軟件編程腳本語言數(shù)據(jù)庫服務(wù)器

如果侵犯了您的權(quán)利,請與我們聯(lián)系,我們將在24小時內(nèi)進行處理、任何非本站因素導(dǎo)致的法律后果,本站均不負任何責(zé)任。

聯(lián)系QQ:835971066 | 郵箱:835971066#qq.com(#換成@)

Copyright © 2002-2020 腳本教程網(wǎng) 版權(quán)所有