公司自用的C語言編程規範

    1. 內容佈局

【規則1-1】遵循統一的佈局順序來書寫頭文件。

說明:以下內容如果某些節不需要,可以忽略。但是其它節要保持該次序。

文件註釋

#ifndef 文件名_H(全大寫)

#define  文件名_H

其它預編譯條件選項

#include(依次爲標準庫頭文件、非標準庫頭文件)

常量和全局宏定義全局宏

全局數據類型

全局變量聲明(extern)

全局函數原型

#endif

【規則1-2】遵循統一的佈局順序來書寫實現文件。

說明:以下內容如果某些節不需要,可以忽略。但是其它節要保持該次序。

文件註釋

#include(依次爲標準庫頭文件、非標準庫頭文件)

常量定義和文件內部使用宏的定義         

文件內部使用的數據類型

全局變量定義和聲明(extern) /*不允許在新增加的實現文件中使用全局變量extern聲明 */

靜態全局變量

全局函數聲明(extern)/*不允許在新增加的實現文件中使用全局函數extern聲明 */

局部函數原型

全局函數實現

局部函數實現

【規則1-3】禁止使用TAB鍵,必須使用空格進行縮進。嵌套的條件編譯採用縮進的格式,{ }之內的代碼塊使用縮進規則對齊。縮進爲4個空格。

 

【規則1-4】if、else、else if、for、while、do、switch、case等所有條件和循環控制語句自佔一行,執行語句不得緊跟其後。不論執行語句有多少都要加 “{”、“ }”,“{”和“}”必須各佔一行。

正例if (ucVal < ucIndexMax)

{

ucVal  = ucIndexMax;

}

反例if (ucVal < ucIndexMax) ucVal = ucIndexMax; 

【規則1-5】定義指針類型的變量,*應放在變量前。

正例float  *pfBuffer = NULL;

反例float*  pfBuffer;

【規則1-6】文件名統一使用小寫。

    1. 註釋要求

【規則2-1】 C語言的註釋符爲“/* … */”。C++語言中,多行註釋採用“/* … */”,單行註釋採用“/*”和“*/”。

 

【規則2-2】一般情況下,源程序有效註釋量必須在20%以上。

正例void Main()

{

if (…) /* 條件說明 */

{  /*  簡單介紹本複合語句的處理過程  */

     while (…) /* 條件說明 */

{  /*  簡單介紹本複合語句的處理過程  */

}  /* end while (條件說明) */   

}  /* end of if (條件說明) */         

}                                                      

【規則2-3】代碼寬度不超過120列;函數體有效長度不超過200行,如果超過需要在函數頭註釋中特別說明原因。

 

【規則2-4】保證代碼和註釋的一致性。修改代碼同時修改相應的註釋,不再有用的註釋要刪除。

 

【規則2-5】在處理變更時,必須在修改代碼的地方註明變更單號和修改者.

 

 

    1. 命名規則

【規則3-1】程序中不要出現僅靠大小寫區分的相似的命名。

 

【規則3-2】使用一致的前綴來區分變量的作用域,使用一致的小寫類型指示符作爲前綴來區分變量的類型屬性。

說明:變量定義:[作用域_][屬性]<變量命名>

[作用域]:                      [屬性]:  

    g_      :  全局變量            uc  : unsigned char 或 byte

    s_      :  靜態變量            c   : char

    空      :  局部變量            w   : 16位無符號數               

                                    sw  : 16位有符號數              

                                    dw  : 32位無符號數                

                                    sdw : 32位有符號數

                                    qw  : 64位無符號數

                                    sqw : 64位有符號數

                                    f   :  浮點數;                

                                    p   : pointer             

                                    a   : 數組,array of TYPE 

                                    str : 字符串              

                                    t   : 結構類型,枚舉,聯合

以上前綴可以進一步組合,在進行組合時,數組和指針類型的前綴指示符必須放在變量類型前綴的首位。

【規則3-3】結構類型名、聯合類型名、枚舉類型名由後綴 _T 結尾。

【規則3-4】程序中局部變量不要與全局變量重名。

 

【規則3-5】儘量避免名字中出現數字編號,如Value1、Value2等,除非邏輯上的確需要編號。

 

 

    1. 變量、常量與類型

【規則4-1】一個變量有且只有一個功能,不能把一個變量用作多種用途。

     

【規則4-2】宏定義中如果包含表達式或變量,表達式和變量必須用小括號括起來。

正例:#define  HANDLE(A, B)   (( A ) / ( B ))

反例:#define  HANDLE(A, B)   (A / B)

【規則4-3】使用宏定義多行語句時, 必須使用 { } 把這些語句括起來。

 

【規則4-4】實現代碼中不允許使用數值,所有用到的地方必須用宏代替.

 

 

 

 

【規則4-5】模塊間接口如果使用簡單類型定義,則必須使用經過統一封裝定義後的BYTE,CHAR, WORD16,SWORD16,WORD32,SWORD32,WORD64,SWORD64等數據類型。在能夠使用自定義數據類型實現的前提下,禁止直接使用C語言提供的原始數據類型,如char,int,long,bool等。

說明:BYTE     8位無符號數                     WORD16    16位無符號數

CHAR     8位有符號數                     SWORD16   16位有符號數

WORD32   32位無符號數                    WORD64    64位無符號數

SWORD32  32位有符號數                    SWORD64   64位有符號數

 

    1. 表達式規則

【規則5-1】在表達式中使用括號和排版,使表達式的運算順序更清晰。

正例:if(     ( (dwYear % 4 == 0) && (dwYear % 100 != 0)  )

   || (dwYear % 400 == 0) )

【規則5-2】避免表達式中的附加功能,不要編寫太複雜的複合表達式。

反例1

dwResult = (adwVar[1]=adwVar[2]++);/* 附加功能:對adwVar[1]賦值,adwVar[2]自增 */

反例2

 c = (a  > b) ?  a : b;

 

【規則5-3】不可將浮點變量用“==”或“!=”與任何數字比較。

 

【規則5-4】在switch語句中,每一個case後面如果相應功能實現代碼,分支必須使用break,最後一個分支必須是default分支。

反例

switch( dat->thisState )

{

  case EV_MASTER_POWER_ON:

            proxyInitialize(&proxyData);

   case EV_DRDYNCONFIG_NOTIFY:

           mhdOnHsdbSwitchEvent(&dat,req);

            break;

default:

       break;

 }

 

【規則5-5】不可在for 循環體內修改循環控制變量,防止for 循環失去控制。

 

【規則5-6】進行“==”比較時,將常量或常數放在“==”號的左邊。

 

正例:if (NULL == ptTail)

 

 

    1. 函數使用

【規則6-1】本模塊向其它模塊提供的接口函數中,需要對輸入參數的正確性和有效性進行檢查。

 

【規則6-2】禁止改寫函數的入參。

 

【規則6-3一個函數的參數之和不要超過5個。

 

 

【規則6-4無論是函數或者宏函數,在使用過程中,傳遞進來的參數要求是變量或者常量,不要涉及表達式。

反例#define OPERAND(a)  ( (a) + (a) )

OPERAND(i++);  /* 這條語句在實現中i其實被增加了兩次,增加了潛在的錯誤 */

【規則6-5】必須對所調用函數的錯誤返回值進行處理。

 

【規則6-6】一個函數內定義的局部變量的大小總和不允許超過1K,特殊情況需要說明原因。

 

【規則6-7】非void類型的函數中每個出口分支都要有返回值.

 

 

 

    1. 資源使用

【規則7-1】對數組、指針、內存地址等的操作,必須注意被操作內存的大小和邊界是否合適,防止內存操作讀取和寫入越界。要求先比較源和目的大小,然後取值小的進行操作。當OSS提供封裝後的內存操作函數後,要求使用封裝的函數。

正例:

CHAR     acName[NAME_SIZE];

CHAR     acOtherName[OTHER_NAME_SIZE];

if(OTHER_NAME_SIZE>NAME_SIZE )

{

     memcpy(acName, acOtherName,NAME_SIZE );

}

else

{

     memcpy(acName, acOtherName,OTHER_NAME_SIZE );

}

 

反例:

CHAR     acName[NAME_SIZE];

CHAR     acOtherName[OTHER_NAME_SIZE];

memcpy(acName, acOtherName,NAME_SIZE );

 

【規則7-3不要忘記字符串包含一個終止符號”\0”,而該符號會佔用一個內存空間,但是strlen統計的長度並沒有將之包含在內。

 

【規則7-4】字符串操作要求使用帶長度限制的接口,比如字符串拷貝規定使用strncpy、 strncat等,禁止使用strcpy、 strcat等,字符串格式化使用snprintf或_snprintf,禁止使用sprintf等。

 

    1. 指針和數組規則

【規則8-1】指針類型變量必須初始化(NULL或者其它確定的值)。

 

【規則8-2】如果變量明確不會被修改,應該增加const屬性,以加強編譯器的檢查。

 

【規則8-3】對指針進行算術操作必須有明確註釋。

正例:      WORD16 *pwMsg = NULL;

      ……

      pwMsg += 5;   /* 向前偏移5個元素,共10個字節 */

【規則8-4】禁止對數組名進行算術運算訪問數組元素,規定使用數組名和數組下標(所有維數)訪問數組元素。

反例:int aucBuf[10],ucVal;

ucVal = *(aucBuf+1); 

正例 :

int aucBuf[10],ucVal;

ucVal= aucBuf[1]

【規則8-5】對指針的操作要求使用括號括起來以明確代碼的語義。

反例:

    WORD  *pwSize=NULL ;

    WORD  wLen = 0 ;   

    wLen=*pwSize+1;

 

正例:

WORD  *pwSize=NULL ;

    WORD  wLen = 0 ;   

    wLen=*(pwSize+1);

 

 

    1. 可測試要求

【規則9-1】在編寫代碼之前,應預先設計好程序調試與測試的方法和手段,並設計好各種調測開關及相應測試代碼(如打印函數等)。

 

    1. 斷言與錯誤處理

【規則10-1】整個軟件系統應該採用統一的斷言。不允許直接使用系統提供的assert,只能使用支撐提供的OSS_ASSERT,並且進行錯誤處理。對較複雜的斷言加上明確的註釋。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章