1. 程式人生 > >怎樣編寫高質量的C程式碼----你真的會麼???

怎樣編寫高質量的C程式碼----你真的會麼???

怎樣編寫高質量的C程式碼—-你真的會麼???

1:編碼規範介紹:

2:巨集觀上的高質量編碼規範

3:微觀上的高質量的編碼規範

編碼規範:
編碼規範的重要性:
程式設計師的態度
1:不太願意測試自己的程式碼
2:不願意REVIEW其他團隊的程式碼

專業的程式設計師:

    專業的程式設計師和業餘程式設計師主要在於態度:
    專業的程式設計師很注重自己的形象,專業的程式設計師表現在程式碼風格上面,
    專業程式設計師才能寫出人能懂的程式碼,作為專業程式設計師,每當寫下一行程式碼的時候,首先記住這是給人讀的,其次是給機器讀的
    保證自己的程式碼儘量少的BUG

業餘程式設計師向專業程式設計師的轉變(不做業餘程式設計師)
1:改變自己的態度
2:從編碼規範開始
3:養成一種嚴謹的工作態度

        仔細設計,編寫程式碼,單元測試,功能測試,程式碼REVIEW

巨集觀上的高質量的編碼規範:

版本和版權的申明
標頭檔案的結構
原始檔的結構
工程目錄的結構
命名規則
程式的版式

版權和版本的申明:
版權和版本的申明位於標頭檔案和定義檔案的開頭,如下:
1:版權資訊
2:檔名稱,識別符號,摘要
3:當前版本好,作者/修改者,完成日期
4:版本歷史資訊

標頭檔案:
標頭檔案開頭出的版權和版本申明
預處理快
函式和結構體申明等

標頭檔案注意點;
1:為了防止標頭檔案被重讀引用,應當用ifndef/define/endif結構產生預處理塊
2:引用標頭檔案
3:標頭檔案中只存在申明不存在定義(變數的宣告定義儘量放在原始檔中)
4:不提倡使用全部變數 extern int value;

原始檔結構:
1:版權或版本申明
2:標頭檔案引用
3:程式的實現體,包括資料和程式碼

工程目錄結構
特點:便於維護
將標頭檔案和定義的檔案分別儲存在不同的目錄
加強資訊隱蔽:
NetWork工程 ——->source
lib
include

命名規則
根據每個公司具體的要求
一般分為駝峰命名法,如:testUi();
和小寫下劃線連線命名法 test_ui();

排版
每行控制在70-80個字元以內

微觀上的高質量的編碼規範

1:程式的健壯性
2:程式設計的優化

程式的健壯性:

1:使用斷言

程式一般分為debug和release版本斷言assert是僅僅在debug版本中起作用的巨集。
#include<assert.h>

    void assert(scalar expression);

    引數是假定的表示式;
assert是一個帶引數的巨集,假定的意思;
assert(sp != NULL);//假設sp不為null,如果為null,就會產生錯誤,程式終止執行;
使用斷言的好處:
    幫助我們跟蹤程式執行和除錯
    輸出一些錯誤的原因
    我們可以自定義一些假定的條件
    它可以捕捉到一些我們不應該發生的非法情況
    注意:在函式的入口處我們可以檢查一些引數的有效性和合法性

簡單例項程式碼:

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>

void out(FILE *spIn)
{
    assert(spIn != NULL);
}
int main(void)
{
    FILE *spIn;
    spIn = fopen("src/a.txt","r");
    assert(spIn != NULL );//為NULL的時候,在斷言這個用法就會終止程式並且會輸出錯誤資訊,捕捉到不應該發生的非法的情況
    out(spIn);
    return  0;  
}

2:複合的表示式

    在程式中儘量使用類似
    a = b = c = 1;
    優勢:
        書寫簡潔
        提高編譯效率
    注意:
        不要使用太過於複雜的表示式
        不要使用多用途的表示式; d = (a = b +c)+r;

3:if語句中:

布林變數與零數值比較
在C語言中,非0為真,0為假
    if(flag) //為真

整型變數與0比較,使用==號進行比較

指標變數與NULL比較,
if(sp == NULL){}

4:使用const提高函式的健壯性:

定義只讀變數  const int a = 10;
可以修飾函式的引數 const struct *stu------>常量指標
函式返回值使用const修飾
    const int* getConstInt(){}//指標函式返回的是常量指標

5:記憶體的管理規則;

使用malloc的時候,返回的是void *,但是是需要去檢查是否為NULL
不要忘記 給陣列和動態記憶體賦予初始化數值,防止將未被初始化的記憶體使用
避免陣列或指標的下表越界
動態記憶體的申請和釋放必須要去成對出現
free完了之後,需要立即將指標設定為NULL

6:指標引數的記憶體傳遞

如果函式的引數是一個指標,不要指望用該指標去申請動態記憶體
如void getmemory(char *p,int num){
    p = (char*)malloc(sizeof(char)* num); //錯誤的使用
}   

不要用return去返回指向"棧記憶體"的指標
char *getString(){
    char *p = "hello";
    return  p;     //錯誤的使用,因為函式內部的區域性變數是存放在棧中的,函式在呼叫完了之後,會將函式棧給釋放,這個時候,釋放出來之後,指標指向記憶體空間的數值的具體是多少就是不可以控制的;
}

7:常量的使用

常量的數值在執行期間是恆定不變的
學會使用巨集#define來解決常量修改的問題,

8:迴圈語句的效率:

在多重迴圈中,如果有可能,應當將最長的迴圈放在最記憶體,最短的迴圈放在最外層,以減少CPU跨切迴圈層的次數;
儘量將邏輯判斷放在迴圈體的外面;