編碼規範很重要,其實他直接影響到了代碼迭代更新的效率和出問題的概率。以下爲本人對網上廣爲流傳的華爲編碼規範的個人總結。(ps:其中有幾個原則實在是精闢的不能再精闢了,當然也有一些存在疑惑,還希望各位大佬不吝賜教)
1.不要使用難懂的技巧性很高的語句,除非很有必要時
高技巧語句不等於高效率的程序,實際上程序的效率關鍵在於算法。這可能是很多初學者最容易犯得錯誤。
2.去掉沒必要的公共變量
公共變量是增大模塊間耦合的原因之一。全局變量雖然好用,但是宜少不宜多這樣能保證數據的安全性。
3.當向公共變量傳遞數據時,最好做數據合法性檢查。
有必要最好做一下,因爲萬一出了問題是不好檢測出來的。
4.構造僅有一個模塊或函數可以修改、創建,而其餘有關模塊或函數只訪問的公共變量,
防止多個不同模塊或函數都可以修改、創建同一公共變量的現象
還是前面講到的數據安全性問題,可以通過靜態函數實現,且整個系統都要保持一致
5.仔細設計結構中元素的佈局與排列順序, 使結構容易理解、 節省佔用空間, 並減少引起
誤用現象
示例:如下結構中的位域排列,將佔較大空間,可讀性也稍差。
typedef struct EXAMPLE_STRU
{
unsigned int valid: 1;
PERSON person;
unsigned int set_flg: 1;
} EXAMPLE;
若改成如下形式,不僅可節省 1 字節空間,可讀性也變好了。
typedef struct EXAMPLE_STRU
{
unsigned int valid: 1;
unsigned int set_flg: 1;
PERSON person ;
} EXAMPLE;
6.儘量減少沒有必要的數據類型默認轉換與強制轉換。
7.對所調用函數的錯誤返回碼要仔細、全面地處理
Linux系統裏好像是不允許有空函數的
8.防止將函數的參數作爲工作變量
將函數的參數作爲工作變量, 有可能錯誤地改變參數內容, 所以很危險。 對必須改
變的參數,最好先用局部變量代之,最後再將該局部變量的內容賦給該參數。
示例:下函數的實現不太好。
void sum_data( unsigned int num, int *data, int *sum )
{
unsigned int count;
*sum = 0;
for (count = 0; count < num; count++)
{
*sum += data[count]; // sum 成了工作變量,不太好。
}
}
若改爲如下,則更好些。
void sum_data( unsigned int num, int *data, int *sum )
{
unsigned int count ;
int sum_temp;
sum_temp = 0;
for (count = 0; count < num; count ++)
{
sum_temp += data[count];
}
*sum = sum_temp;
}
9.一個函數僅完成一件功能。
10.避免設計多參數函數,不使用的參數從接口中去掉。
目的減少函數間接口的複雜度,參數多的話可以通過結構體實現
11.非調度函數應減少或防止控制參數,儘量只使用數據參數
避免函數功能不明確,給調試帶來麻煩
示例:如下函數構造不太合理。
int add_sub( int a, int b, unsigned char add_sub_flg )
{
if (add_sub_flg == INTEGER_ADD)
{
return (a + b);
}
else
{
return (a - b);
}
}
不如分爲如下兩個函數清晰。
int add( int a, int b )
{
return (a + b);
}
int sub( int a, int b )
{
return (a - b);
}
12.檢查函數所有參數輸入的有效性
功能不明確較小的函數,特別是僅有一個上級函數調用它時, 應考慮把它合併到上級
函數中, 而不必單獨存在
13.設計高扇入、 合理扇出(小於7) 的函數。
函數較合理的扇出(調度函數除外) 通常是 3-5.較良好的軟件結構通常是頂層函數的扇出較高, 中層函數的扇出較少, 而底層函數則扇入到公共模塊中。還是強調函數的高複用性和可讀性
14.避免使用BOOL參數
TURE/FALSE 的含義是非常模糊的,這點確實有點驚訝,對於那些內存要求不是很苛刻的能不用就不用吧
15.對於提供了返回值的函數, 在引用時最好使用其返回值。
16.當一個變量名較長且有較多引用時(一般是結構的成員), 可以用一個
意義相當的宏代替
也可以定義一個局部變量,在用之前對局部變量賦值
17.在同一項目組或產品組內, 調測打印出的信息串的格式要有統一的形式。 信息串中至少
要有所在模塊名(或源文件名) 及行號
行號和文件名可以用宏__LINE__和__FILE__實現
18.使用斷言來發現軟件問題, 提高代碼可測性。
斷言可以對在系統中隱藏很深, 用其它手段極難發現的問題進行定位
示例:下面是 C 語言中的一個斷言,用宏來設計的。(其中 NULL 爲 0L)
#ifdef _EXAM_ASSERT_TEST_ // 若使用斷言測試
void exam_assert( char * file_name, unsigned int line_no )
{
printf( "\n[EXAM]Assert failed: %s, line %u\n",file_name, line_no );
abort( );
}
#define EXAM_ASSERT( condition )
if (condition) // 若條件成立,則無動作
NULL;
else // 否則報告
exam_assert( __FILE__, __LINE__ )
#else // 若不使用斷言測試
#define EXAM_ASSERT(condition) NULL
#endif /* end of ASSERT */
19.在編寫代碼之前, 應預先設計好程序調試與測試的方法和手段, 並設計好各種調測開關
及相應測試代碼如打印函數等
20.在保證軟件系統的正確性、 穩定性、可讀性及可測性的前提下, 提高代碼效率。
21.避免循環體內含判斷語句, 應將循環語句置於判斷語句的代碼塊之中
筆者確實踩過這樣的坑,並且真的很難發現是什麼問題。另外循環嵌套儘量不要超過三層且不要太複雜。
22.儘量用乘法或其它方法代替除法,特別是浮點運算中的除法。
浮點運算除法要佔用較多 CPU 資源。應爲一般的cpu只有硬件乘法器
23.過程/函數中申請的(爲打開文件而使用的)文件句柄,在過程/函數退出之前要關閉。
分配的內存不釋放以及文件句柄不關閉, 是較常見的錯誤, 而且稍不注意就有可能發生。這類錯誤往往會引起很嚴重後果,且難以定位
24.有可能的話, if語句儘量加上else分支, 對沒有else分支的語句要小心對待; switch
語句必須有default分支。
25.時刻注意表達式是否會上溢、 下溢。
示例:如下程序將造成變量下溢。
unsigned char size ;
while (size-- >= 0) // 將出現下溢
{
... // program code
}
26.打開編譯器的所有警告開關對程序進行編譯
27.某些語句經編譯後產生警告,但如果你認爲它是正確的,那麼應通過某種手段去掉告
警信息
示例:
#pragma warn -rvl // 關閉告警
int examples_fun( void )
{
// 程序,但無 return 語句。
}
#pragma warn +rvl // 打開告警
28.使用代碼檢查工具(如C語言用PC-Lint)對源程序檢查。使用軟件工具(如 LogiSCOPE)進行代碼審查
用過其中一個,效果不理想可能是不會用吧
29.不應通過“試” 來解決問題,應尋找問題的根本原因。
最精闢的原則之一,可很多人就是通過“試”
30.對自動消失的錯誤進行分析,搞清楚錯誤是如何消失的
最精闢的原則之一,對於提高能力有很大幫助