天天看點

程式設計修養(六)

23、static的使用

————————

static關鍵字,表示了“靜态”,一般來說,他會被經常用于變量和函數。一個static的變量,其實就是全局變量,隻不過他是有作用域的全局變量。比如一個函數中的static變量:

char*

getConsumerName()

{

    static int cnt = 0;

    ....

    cnt++;

}

cnt變量的值會跟随着函數的調用次而遞增,函數退出後,cnt的值還存在,隻是cnt隻能在函數中才能被通路。而cnt的記憶體也隻會在函數第一次被調用時才會被配置設定和初始化,以後每次進入函數,都不為static配置設定了,而直接使用上一次的值。

對于一些被經常調用的函數内的常量,最好也聲明成static(參見第12條)

但static的最多的用處卻不在這裡,其最大的作用的控制通路,在C中如果一個函數或是一個全局變量被聲明為static,那麼,這個函數和這個全局變量,将隻能在這個C檔案中被通路,如果别的C檔案中調用這個C檔案中的函數,或是使用其中的全局(用extern關鍵字),将會發生連結時錯誤。這個特性可以用于資料和程式保密。

24、函數中的代碼尺寸

——————————

一個函數完成一個具體的功能,一般來說,一個函數中的代碼最好不要超過600行左右,越少越好,最好的函數一般在100行以内,300行左右的孫函數就差不多了。有證據表明,一個函數中的代碼如果超過500行,就會有和别的函數相同或是相近的代碼,也就是說,就可以再寫另一個函數。

另外,函數一般是完成一個特定的功能,千萬忌諱在一個函數中做許多件不同的事。函數的功能越單一越好,一方面有利于函數的易讀性,另一方面更有利于代碼的維護和重用,功能越單一表示這個函數就越可能給更多的程式提供服務,也就是說共性就越多。

雖然函數的調用會有一定的開銷,但比起軟體後期維護來說,增加一些運作時的開銷而換來更好的可維護性和代碼重用性,是很值得的一件事。

25、typedef的使用

—————————

typedef是一個給類型起别名的關鍵字。不要小看了它,它對于你代碼的維護會有很好的作用。比如C中沒有bool,于是在一個軟體中,一些程式員使用int,一些程式員使用short,會比較混亂,最好就是用一個typedef來定義,如:

    typedef char bool;

一般來說,一個C的工程中一定要做一些這方面的工作,因為你會涉及到跨平台,不同的平台會有不同的字長,是以利用預編譯和typedef可以讓你最有效的維護你的代碼,如下所示:

    #ifdef SOLARIS2_5

      typedef boolean_t     BOOL_T;

    #else

      typedef int           BOOL_T;

    #endif

    typedef short           INT16_T;

    typedef unsigned short  UINT16_T;

    typedef int             INT32_T;

    typedef unsigned int    UINT32_T;

    #ifdef WIN32

      typedef _int64        INT64_T;

      typedef long long     INT64_T;

    typedef float           FLOAT32_T;

    typedef char*           STRING_T;

    typedef unsigned char   BYTE_T;

    typedef time_t          TIME_T; 

    typedef INT32_T         PID_T;

使用typedef的其它規範是,在結構和函數指針時,也最好用typedef,這也有利于程式的易讀和可維護性。如:

    typedef struct _hostinfo { 

        HOSTID_T   host; 

        INT32_T    hostId; 

        STRING_T   hostType; 

        STRING_T   hostModel; 

        FLOAT32_T  cpuFactor; 

        INT32_T    numCPUs;

        INT32_T    nDisks;

        INT32_T    memory;

        INT32_T    swap;

    } HostInfo;

    typedef INT32_T (*RsrcReqHandler)(

     void *info,

     JobArray *jobs, 

     AllocInfo *allocInfo,

     AllocList *allocList);

C++中這樣也是很讓人易讀的:

    typedef CArray<HostInfo, HostInfo&> HostInfoArray;

于是,當我們用其定義變量時,會顯得十分易讀。如:

    HostInfo* phinfo;

    RsrcReqHandler* pRsrcHand;

這種方式的易讀性,在函數的參數中十分明顯。

關鍵是在程式種使用typedef後,幾乎所有的程式中的類型聲明都顯得那麼簡潔和清淅,而且易于維護,這才是typedef的關鍵。

26、為常量聲明宏

最好不要在程式中出現數字式的“寫死”,如:

    int user[120];

為這個120聲明一個宏吧。為所有出現在程式中的這樣的常量都聲明一個宏吧。比如TimeOut的時間,最大的使用者數量,還有其它,隻要是常量就應該聲明成宏。如果,突然在程式中出現下面一段代碼,

    for ( i=0; i<120; i++){

        ....

    }

120是什麼?為什麼會是120?這種“寫死”不僅讓程式很讀,而且也讓程式很不好維護,如果要改變這個數字,得同時對所有程式中這個120都要做修改,這對修改程式的人來說是一個很大的痛苦。是以還是把常量聲明成宏,這樣,一改百改,而且也很利于程式閱讀。

    #define MAX_USR_CNT 120

    for ( i=0; i<MAX_USER_CNT; i++){

這樣就很容易了解這段程式的意圖了。

有的程式員喜歡為這種變量聲明全局變量,其實,全局變量應該盡量的少用,全局變量不利于封裝,也不利于維護,而且對程式執行空間有一定的開銷,一不小心就造成系統換頁,造成程式執行速度效率等問題。是以聲明成宏,即可以免去全局變量的開銷,也會有速度上的優勢。

27、不要為宏定義加分号

———————————

有許多程式員不知道在宏定義時是否要加分号,有時,他們以為宏是一條語句,應該要加分号,這就錯了。當你知道了宏的原理,你會贊同我為會麼不要為宏定義加分号的。看一個例子:

    #define MAXNUM 1024;

這是一個有分号的宏,如果我們這樣使用:

    half = MAXNUM/2;

    if ( num < MAXNUM )

等等,都會造成程式的編譯錯誤,因為,當宏展開後,他會是這個樣子的:

    half = 1024;/2;

    if ( num < 1024; )

是的,分号也被展進去了,是以造成了程式的錯誤。請相信我,有時候,一個分号會讓你的程式出現成百個錯誤。是以還是不要為宏加最後一個分号,哪怕是這樣:

    #define LINE    "================================="

    #define PRINT_LINE  printf(LINE)

    #define PRINT_NLINE(n)  while ( n-- >0 ) { PRINT_LINE; }

都不要在最後加上分号,當我們在程式中使用時,為之加上分号,

    main()

    {

        char *p = LINE;

        PRINT_LINE;

這一點非常符合習慣,而且,如果忘加了分号,編譯器給出的錯誤提示,也會讓我們很容易看懂的。

本文轉自 haoel 51CTO部落格,原文連結:http://blog.51cto.com/haoel/124708,如需轉載請自行聯系原作者

繼續閱讀