2.1 注釋的原則
注釋的目的是解釋代碼的目的、功能和采用的方法,提供代碼以外的信息,幫助讀者理解代碼,防止沒必要的重復注釋信息。 示例:如下注釋意義不大。
/* if receive_flag is TRUE */
if (receive_flag)
而如下的注釋則給出了額外有用的信息。
/* if mtp receive a message from links */
if (receive_flag)
?
2.2 說明性文件頭部應進行注釋
說明性文件(如頭文件.h 文件、.inc 文件、.def 文件、編譯說明文件.cfg 等)頭部應進行注釋,注釋必須列出:版權說明、版本號、生成日期、作者、內容、功能、與其它文件的關系、修改日志等,頭文件的注釋中還應有函數功能簡要說明。
示例:下面這段頭文件的頭注釋比較標準,當然,并不局限于此格式,但上述信息建議要包含在內。
/**
?* Copyright (C), 1988-1999, Huawei Tech. Co., Ltd.
?* File name:????? // 文件名
?* Author:?????? Version:??????? Date: // 作者、版本及完成日期
?* Description:??? // 用于詳細說明此程序文件完成的主要功能,與其他模塊
????????????????? // 或函數的接口,輸出值、取值范圍、含義及參數間的控
????????????????? // 制、順序、獨立或依賴等關系
?* Others:???????? // 其它內容的說明
?* Function List:? // 主要函數列表,每條記錄應包括函數名及功能簡要說明
??? 1. ....
?* History:??????? // 修改歷史記錄列表,每條修改記錄應包括修改日期、修改
????????????????? // 者及修改內容簡述
??? 1. Date:
?????? Author:
?????? Modification:
?? 2. ...
?*/
?
2.3 源文件頭部應進行注釋
源文件頭部應進行注釋,列出:版權說明、版本號、生成日期、作者、模塊目的/功能、主要函數及其功能、修改日志等。
示例:下面這段源文件的頭注釋比較標準,當然,并不局限于此格式,但上述信息建議要包含在內。
/**
?* Copyright (C), 1988-1999, Huawei Tech. Co., Ltd.
?* FileName: test.cpp
?* Author:??????? Version :????????? Date:
?* Description:???? // 模塊描述
?* Version:???????? // 版本信息
?* Function List:?? // 主要函數及其功能
??? 1. -------
?* History:???????? // 歷史修改記錄
????? <author>? <time>?? <version >?? <desc>
????? David??? 96/10/12???? 1.0???? build this moudle
?*/
說明:Description一項描述本文件的內容、功能、內部各部分之間的關系及本文件與其它文件關系等。History是修改歷史記錄列表,每條修改記錄應包括修改日期、修改者及修改內容簡述。
?
2.4 函數頭部應進行注釋
函數頭部應進行注釋,列出:函數的目的/ 功能、輸入參數、輸出參數、返回值、調用關系(函數、表)等。
示例1:下面這段函數的注釋比較標準,當然,并不局限于此格式,但上述信息建議要包含在內。
/**
?* Function:?????? // 函數名稱
?* Description:??? // 函數功能、性能等的描述
?* Calls: ?????????// 被本函數調用的函數清單
?* Called By:????? // 調用本函數的函數清單
?* Table Accessed: // 被訪問的表(此項僅對于牽扯到數據庫操作的程序)
?* Table Updated:? // 被修改的表(此項僅對于牽扯到數據庫操作的程序)
?* Input:????????? // 輸入參數說明,包括每個參數的作
????????????????? // 用、取值說明及參數間關系。
?* Output:???????? // 對輸出參數的說明。
?* Return:???????? // 函數返回值的說明
?* Others:???????? // 其它說明
?*/
對于某些函數,其部分參數為傳入值,而部分參數為傳出值,所以對參數要詳細說明該參數是入口參數,還是出口參數,對于某些意義不明確的參數還要做詳細說明(例如:以角度作為參數時,要說明該角度參數是以弧度(PI),還是以度為單位),對既是入口又是出口的變量應該在入口和出口處同時標明。等等。
在注釋中詳細注明函數的適當調用方法,對于返回值的處理方法等。在注釋中要強調調用時的危險方面,可能出錯的地方。
?
2.5 進行注釋時的注意事項
(1)建議邊寫代碼邊注釋,修改代碼同時修改相應的注釋,以保證注釋與代碼的一致性。不再有用的注釋要刪除。
(2)注釋的內容要清楚、明了,含義準確,防止注釋二義性。說明:錯誤的注釋不但無益反而有害。
(3)避免在注釋中使用縮寫,特別是非常用縮寫。在使用縮寫時或之前,應對縮寫進行必要的說明。
(4)注釋應與其描述的代碼相近,對代碼的注釋應放在其上方或右方(對單條語句的注釋)相鄰位置,不可放在下面。除非必要,不應在代碼或表達中間插入注釋,否則容易使代碼可理解性變差。
示例:如下例子不符合規范。
例1:
/* get replicate sub system index and net indicator */
?
repssn_ind = ssn_data[index].repssn_index;
repssn_ni = ssn_data[index].ni;
例2:
repssn_ind = ssn_data[index].repssn_index;
repssn_ni = ssn_data[index].ni;
/* get replicate sub system index and net indicator */
應如下書寫
/* get replicate sub system index and net indicator */
repssn_ind = ssn_data[index].repssn_index;
repssn_ni = ssn_data[index].ni;
(5)對于所有有物理含義的變量、常量,如果其命名不是充分自注釋的,在聲明時都必須加以注釋,說明其物理含義。變量、常量、宏的注釋應放在其上方相鄰位置或右方。
示例:
/* active statistic task number */
#define MAX_ACT_TASK_NUMBER 1000
#define MAX_ACT_TASK_NUMBER 1000 /* active statistic task number */
(6)數據結構聲明( 包括數組、結構、類、枚舉等) ,如果其命名不是充分自注釋的,必須加以注釋。對數據結構的注釋應放在其上方相鄰位置,不可放在下面;對結構中的每個域的注釋放在此域的右方。
示例:可按如下形式說明枚舉/數據/聯合結構。
/* sccp interface with sccp user primitive message name */
enum? SCCP_USER_PRIMITIVE
{
??? N_UNITDATA_IND, /* sccp notify sccp user unit data come */
??? N_NOTICE_IND,?? /* sccp notify user the No.7 network can not */
??????????????????? /* transmission this message */
??? N_UNITDATA_REQ, /* sccp user's unit data transmission request*/
};
(7)全局變量要有較詳細的注釋,包括對其功能、取值范圍、哪些函數或過程存取它以及存取時注意事項等的說明。
示例:
/* The ErrorCode when SCCP translate */
/* Global Title failure, as follows */????? // 變量作用、含義
/* 0 - SUCCESS?? 1 - GT Table error */
/* 2 - GT error? Others - no use? */?????? // 變量取值范圍
/* only? function? SCCPTranslate() in */
/* this modual can modify it,? and? other */
/* module can visit it through call */
/* the? function GetGTTransErrorCode() */??? // 使用方法
BYTE g_GTTranErrorCode;
(8)注釋與所描述內容進行同樣的縮排,讓程序排版整齊,并方便注釋的閱讀與理解。
示例:如下例子,排版不整齊,閱讀稍感不方便。
void example_fun( void )
{
/* code one comments */
??? CodeBlock One
?
??????? /* code two comments */
??? CodeBlock Two
}
應改為如下布局。
void example_fun( void )
{
??? /* code one comments */
??? CodeBlock One
?
??? /* code two comments */
??? CodeBlock Two
}
(9)將注釋與其上面的代碼用空行隔開。
示例:如下例子,顯得代碼過于緊湊。
/* code one comments */
program code one
/* code two comments */
program code two
應如下書寫
/* code one comments */
program code one
?
/* code two comments */
program code two
(10)對變量的定義和分支語句(條件分支、循環語句等)必須編寫注釋。這些語句往往是程序實現某一特定功能的關鍵,對于維護人員來說,良好的注釋幫助更好的理解程序,有時甚至優于看設計文檔。
(11)對于switch 語句下的case 語句,如果因為特殊情況需要處理完一個case 后進入下一個case 處理(即上一個case后無break),必須在該case 語句處理完、下一個case 語句前加上明確的注釋,以清楚表達程序編寫者的意圖,有效防止無故遺漏break語句(可避免后期維護人員對此感到迷惑:原程序員是遺漏了break語句還是本來就不應該有)。示例:
case CMD_DOWN:
??? ProcessDown();
??? break;
case CMD_FWD:
??? ProcessFwd();
??? if (...)
??? {
??????? ...
??????? break;
??? } else
??? {
??????? ProcessCFW_B();?? // now jump into case CMD_A
??? }
case CMD_A:
??? ProcessA();
??? break;
...
(12)在程序塊的結束行右方加注釋標記,以表明某程序塊的結束。當代碼段較長,特別是多重嵌套時,這樣做可以使代碼更清晰,更便于閱讀。示例:參見如下例子。
if (...)
{
??? program code
??? while (index < MAX_INDEX)
??? {
??????? program code
??? } /* end of while (index < MAX_INDEX) */ // 指明該條while語句結束
} /* end of? if (...)*/ // 指明是哪條if語句結束
(13)在順序執行的程序中,每隔3—5行語句,應當加一個注釋,注明這一段語句所組成的小模塊的作用。對于自己的一些比較獨特的思想要求在注釋中標明。
(14)注釋格式盡量統一,建議使用“/* …… */”。
(15)注釋應考慮程序易讀及外觀排版的因素,使用的語言若是中、英兼有的,建議多使用中文,除非能用非常流利準確的英文表達——注釋語言不統一,影響程序易讀性和外觀排版,出于對維護人員的考慮,建議使用中文。