欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
編程(下)

編程---進(jìn)(下)

11、出錯信息的處理

你會(huì )處理出錯信息嗎?哦,它并不是簡(jiǎn)單的輸出??聪旅娴氖纠?br>
  if ( p == NULL ){
    printf ( "ERR: The pointer is NULLn" );
  }
  
告別學(xué)生時(shí)代的編程吧。這種編程很不利于維護和管理,出錯信息或是提示信息,應該統一處理,而不是像上面這樣,寫(xiě)成一個(gè)“硬編碼”。第10條對這方面的處理做了一部分說(shuō)明。如果要管理錯誤信息,那就要有以下的處理:

  
  #define   ERR_NO_ERROR  0 
  #define   ERR_OPEN_FILE  1 
  #define   ERR_SEND_MESG  2 
  #define   ERR_BAD_ARGS  3 
  #define   ERR_MEM_NONE  4 
  #define   ERR_SERV_DOWN  5 
  #define   ERR_UNKNOW_INFO 6 
  #define   ERR_SOCKET_ERR 7 
  #define   ERR_PERMISSION 8 
  #define   ERR_BAD_FORMAT 9 
  #define   ERR_TIME_OUT  10 
  
  
  char* errmsg[] = {
        "No error",        
        "Open file error",    
        "Failed in sending/receiving a message", 
        "Bad arguments", 
        "Memeroy is not enough",
        "Service is down; try later",
        "Unknow information",
        "A socket operation has failed",
        "ermission denied",
        "Bad configuration file format", 
       "Communication time out",
  };
               
  
  long errno = 0;
  
  
  void perror( char* info)
  {
    if ( info ){
      printf("%s: %sn", info, errmsg[errno] );
      return;
    }
    
    printf("Error: %sn", errmsg[errno] );
  }
這個(gè)基本上是ANSI的錯誤處理實(shí)現細節了,于是當你程序中有錯誤時(shí)你就可以這樣處理:
  bool CheckPermission( char* userName )
  {
    if ( strcpy(userName, "root") != 0 ){
      errno = ERR_PERMISSION_DENIED;
      return (FALSE);
    }
    
    ...
  }
  
  main()
  {
    ...
    if (! CheckPermission( username ) ){
      perror("main()");
    }
    ...
  }
               
一個(gè)即有共性,也有個(gè)性的錯誤信息處理,這樣做有利同種錯誤出一樣的信息,統一用戶(hù)界面,而不會(huì )因為文件打開(kāi)失敗,A程序員出一個(gè)信息,B程序員又出一個(gè)信息。而且這樣做,非常容易維護。代碼也易讀。

當然,物極必反,也沒(méi)有必要把所有的輸出都放到errmsg中,抽取比較重要的出錯信息或是提示信息是其關(guān)鍵,但即使這樣,這也包括了大多數的信息。
12、常用函數和循環(huán)語(yǔ)句中的被計算量

看一下下面這個(gè)例子:

  for( i=0; i<1000; i++ ){
    GetLocalHostName( hostname );
    ...
  }
  
GetLocalHostName的意思是取得當前計算機名,在循環(huán)體中,它會(huì )被調用1000次啊。這是多么的沒(méi)有效率的事啊。應該把這個(gè)函數拿到循環(huán)體外,這樣只調用一次,效率得到了很大的提高。雖然,我們的編譯器會(huì )進(jìn)行優(yōu)化,會(huì )把循環(huán)體內的不變的東西拿到循環(huán)外面,但是,你相信所有編譯器會(huì )知道哪些是不變的嗎?我覺(jué)得編譯器不可靠。最好還是自己動(dòng)手吧。

同樣,對于常用函數中的不變量,如:

GetLocalHostName(char* name)
{
  char funcName[] = "GetLocalHostName";
  
  sys_log( "%s begin......", funcName );
  ...
  sys_log( "%s end......", funcName );
}

如果這是一個(gè)經(jīng)常調用的函數,每次調用時(shí)都要對funcName進(jìn)行分配內存,這個(gè)開(kāi)銷(xiāo)很大啊。把這個(gè)變量聲明成static吧,當函數再次被調用時(shí),就會(huì )省去了分配內存的開(kāi)銷(xiāo),執行效率也很好。
  
13、函數名和變量名的命名

我看到許多程序對變量名和函數名的取名很草率,特別是變量名,什么a,b,c,aa,bb,cc,還有什么flag1,flag2, cnt1, cnt2,這同樣是一種沒(méi)有“修養”的行為。即便加上好的注釋。好的變量名或是函數名,我認為應該有以下的規則:
  
1) 直觀(guān)并且可以拼讀,可望文知意,不必“解碼”。
2) 名字的長(cháng)度應該即要最短的長(cháng)度,也要能最大限度的表達其含義。
3) 不要全部大寫(xiě),也不要全部小寫(xiě),應該大小寫(xiě)都有,如:GetLocalHostName 或是 UserAccount。
4) 可以簡(jiǎn)寫(xiě),但簡(jiǎn)寫(xiě)得要讓人明白,如:ErrorCode -> ErrCode, ServerListener -> ServLisner,UserAccount -> UsrAcct 等。
5) 為了避免全局函數和變量名字沖突,可以加上一些前綴,一般以模塊簡(jiǎn)稱(chēng)做為前綴。
6) 全局變量統一加一個(gè)前綴或是后綴,讓人一看到這個(gè)變量就知道是全局的。
7) 用匈牙利命名法命名函數參數,局部變量。但還是要堅持“望文生意”的原則。
8) 與標準庫(如:STL)或開(kāi)發(fā)庫(如:MFC)的命名風(fēng)格保持一致。
  
14、函數的傳值和傳指針

向函數傳參數時(shí),一般而言,傳入非const的指針時(shí),就表示,在函數中要修改這個(gè)指針把指內存中的數據。如果是傳值,那么無(wú)論在函數內部怎么修改這個(gè)值,也影響不到傳過(guò)來(lái)的值,因為傳值是只內存拷貝。
什么?你說(shuō)這個(gè)特性你明白了,好吧,讓我們看看下面的這個(gè)例程:

void
GetVersion(char* pStr)
{
  pStr = malloc(10);
  strcpy ( pStr, "2.0" );
}
main()
{
  char* ver = NULL;
  GetVersion ( ver );
  ...
  ...
  free ( ver );
}

我保證,類(lèi)似這樣的問(wèn)題是一個(gè)新手最容易犯的錯誤。程序中妄圖通過(guò)函數GetVersion給指針ver分配空間,但這種方法根本沒(méi)有什么作用,原因就是--這是傳值,不是傳指針。你或許會(huì )和我爭論,我分明傳的時(shí)指針???再仔細看看,其實(shí),你傳的是指針其實(shí)是在傳值。

15、修改別人程序的修養

當你維護別人的程序時(shí),請不要非常主觀(guān)臆斷的把已有的程序刪除或是修改。我經(jīng)??吹接械某绦騿T直接在別人的程序上修改表達式或是語(yǔ)句。修改別人的程序時(shí),請不要刪除別人的程序,如果你覺(jué)得別人的程序有所不妥,請注釋掉,然后添加自己的處理程序,必竟,你不可能100%的知道別人的意圖,所以為了可以恢復,請不依賴(lài)于CVS或是SourceSafe這種版本控制軟件,還是要在源碼上給別人看到你修改程序的意圖和步驟。這是程序維護時(shí),一個(gè)有修養的程序員所應該做的。

如下所示,這就是一種比較好的修改方法:

  
  
  
   char* p = ( char* )calloc( 10, sizeof char );
  
  ...

當然,這種方法是在軟件維護時(shí)使用的,這樣的方法,可以讓再維護的人很容易知道以前的代碼更改的動(dòng)作和意圖,而且這也是對原作者的一種尊敬。

以“注釋 - 添加”方式修改別人的程序,要好于直接刪除別人的程序。

16、把相同或近乎相同的代碼形成函數和宏

有人說(shuō),最好的程序員,就是最喜歡“偷懶”的程序,其中不無(wú)道理。

如果你有一些程序的代碼片段很相似,或直接就是一樣的,請把他們放在一個(gè)函數中。而如果這段代碼不多,而且會(huì )被經(jīng)常使用,你還想避免函數調用的開(kāi)銷(xiāo),那么就把他寫(xiě)成宏吧。

千萬(wàn)不要讓同一份代碼或是功能相似的代碼在多個(gè)地方存在,不然如果功能一變,你就要修改好幾處地方,這種會(huì )給維護帶來(lái)巨大的麻煩,所以,做到“一改百改”,還是要形成函數或是宏。

17、表達式中的括號

如果一個(gè)比較復雜的表達式中,你并不是很清楚各個(gè)操作符的憂(yōu)先級,即使是你很清楚優(yōu)先級,也請加上括號,不然,別人或是自己下一次讀程序時(shí),一不小心就看走眼理解錯了,為了避免這種“誤解”,還有讓自己的程序更為清淅,還是加上括號吧。

比如,對一個(gè)結構的成員取地址:

  GetUserAge( &( UserInfo->age ) );
雖然,&UserInfo->age中,->操作符的優(yōu)先級最高,但加上一個(gè)括號,會(huì )讓人一眼就看明白你的代碼是什么意思。
再比如,一個(gè)很長(cháng)的條件判斷:
if ( ( ch[0] >= ′0′ || ch[0] <= ′9′ ) &&
   ( ch[1] >= ′a′ || ch[1] <= ′z′ ) &&
   ( ch[2] >= ′A′ || ch[2] <= ′Z′ )  )
  
括號,再加上空格和換行,你的代碼是不是很容易讀懂了?  

18、函數參數中的const

對于一些函數中的指針參數,如果在函數中只讀,請將其用const修飾,這樣,別人一讀到你的函數接口時(shí),就會(huì )知道你的意圖是這個(gè)參數是[in],如果沒(méi)有const時(shí),參數表示[in/out],注意函數接口中的const使用,利于程序的維護和避免犯一些錯誤。

雖然,const修飾的指針,如:const char* p,在C中一點(diǎn)用也沒(méi)有,因為不管你的聲明是不是const,指針的內容照樣能改,因為編譯器會(huì )強制轉換,但是加上這樣一個(gè)說(shuō)明,有利于程序的閱讀和編譯。因為在C中,修改一個(gè)const指針所指向的內存時(shí),會(huì )報一個(gè)Warning。這會(huì )引起程序員的注意。

C++中對const定義的就很?chē)栏窳?,所以C++中要多多的使用const,const的成員函數,const的變量,這樣會(huì )對讓你的代碼和你的程序更加完整和易讀。(關(guān)于C++的const我就不多說(shuō)了)

19、函數的參數個(gè)數(多了請用結構)

函數的參數個(gè)數最好不要太多,一般來(lái)說(shuō)6個(gè)左右就可以了,眾多的函數參數會(huì )讓讀代碼的人一眼看上去就很頭昏,而且也不利于維護。如果參數眾多,還請使用結構來(lái)傳遞參數。這樣做有利于數據的封裝和程序的簡(jiǎn)潔性。

也利于使用函數的人,因為如果你的函數個(gè)數很多,比如12個(gè),調用者很容易搞錯參數的順序和個(gè)數,而使用結構struct來(lái)傳遞參數,就可以不管參數的順序。

而且,函數很容易被修改,如果需要給函數增加參數,不需要更改函數接口,只需更改結構體和函數內部處理,而對于調用函數的程序來(lái)說(shuō),這個(gè)動(dòng)作是透明的。

20、函數的返回類(lèi)型,不要省略

我看到很多程序寫(xiě)函數時(shí),在函數的返回類(lèi)型方面不太注意。如果一個(gè)函數沒(méi)有返回值,也請在函數前面加上void的修飾。而有的程序員偷懶,在返回int的函數則什么不修飾(因為如果不修飾,則默認返回int),這種習慣很不好,還是為了原代碼的易讀性,加上int吧。
所以函數的返回值類(lèi)型,請不要省略。

另外,對于void的函數,我們往往會(huì )忘了return,由于某些C/C++的編譯器比較敏感,會(huì )報一些警告,所以即使是void的函數,我們在內部最好也要加上return的語(yǔ)句,這有助于代碼的編譯。

21、goto語(yǔ)句的使用

N年前,軟件開(kāi)發(fā)的一代宗師--迪杰斯特拉(Dijkstra)說(shuō)過(guò):“goto statment is harmful !!”,并建議取消goto語(yǔ)句。因為goto語(yǔ)句不利于程序代碼的維護性。

這里我也強烈建議不要使用goto語(yǔ)句,除非下面的這種情況:
  #define FREE(p) if(p) {
            free(p);
            p = NULL;
          }
  main()
  {
    char *fname=NULL, *lname=NULL, *mname=NULL;
    fname = ( char* ) calloc ( 20, sizeof(char) );
    if ( fname == NULL ){
      goto ErrHandle;
    }
    lname = ( char* ) calloc ( 20, sizeof(char) );
    if ( lname == NULL ){
      goto ErrHandle;
    }
    mname = ( char* ) calloc ( 20, sizeof(char) );
    if ( mname == NULL ){
      got-

o ErrHandle;
    }
    
    ......
  
    
   ErrHandle:
    FREE(fname);
    FREE(lname);
    FREE(mname);
    ReportError(ERR_NO_MEMOEY);
   }

也只有在這種情況下,goto語(yǔ)句會(huì )讓你的程序更易讀,更容易維護。(在用嵌C來(lái)對數據庫設置游標操作時(shí),或是對數據庫建立鏈接時(shí),也會(huì )遇到這種結構)

22、宏的使用

很多程序員不知道C中的“宏”到底是什么意思?特別是當宏有參數的時(shí)候,經(jīng)常把宏和函數混淆。我想在這里我還是先講講“宏”,宏只是一種定義,他定義了一個(gè)語(yǔ)句塊,當程序編譯時(shí),編譯器首先要執行一個(gè)“替換”源程序的動(dòng)作,把宏引用的地方替換成宏定義的語(yǔ)句塊,就像文本文件替換一樣。這個(gè)動(dòng)作術(shù)語(yǔ)叫“宏的展開(kāi)”

使用宏是比較“危險”的,因為你不知道宏展開(kāi)后會(huì )是什么一個(gè)樣子。例如下面這個(gè)宏:
  #define MAX(a, b)   a>b?a:b

當我們這樣使用宏時(shí),沒(méi)有什么問(wèn)題: MAX( num1, num2 ); 因為宏展開(kāi)后變成 num1>num2?num1:num2;。但是,如果是這樣調用的,MAX( 17+32, 25+21 ); 呢,編譯時(shí)出現錯誤,原因是,宏展開(kāi)后變成:17+32>25+21?17+32:25+21,哇,這是什么???
所以,宏在使用時(shí),參數一定要加上括號,上述的那個(gè)例子改成如下所示就能解決問(wèn)題了。

  #define MAX( (a), (b) )   (a)>(b)?(a)b)
  
即使是這樣,也不這個(gè)宏也還是有Bug,因為如果我這樣調用 MAX(i++, j++); ,經(jīng)過(guò)這個(gè)宏以后,i和j都被累加了兩次,這絕不是我們想要的。
  
所以,在宏的使用上還是要謹慎考慮,因為宏展開(kāi)是的結果是很難讓人預料的。而且雖然,宏的執行很快(因為沒(méi)有函數調用的開(kāi)銷(xiāo)),但宏會(huì )讓源代碼澎漲,使目標文件尺寸變大,(如:一個(gè)50行的宏,程序中有1000個(gè)地方用到,宏展開(kāi)后會(huì )很不得了),相反不能讓程序執行得更快(因為執行文件變大,運行時(shí)系統換頁(yè)頻繁)。

因此,在決定是用函數,還是用宏時(shí)得要小心。

23、static的使用

static關(guān)鍵字,表示了“靜態(tài)”,一般來(lái)說(shuō),他會(huì )被經(jīng)常用于變量和函數。一個(gè)static的變量,其實(shí)就是全局變量,只不過(guò)他是有作用域的全局變量。比如一個(gè)函數中的static變量:

char*
getConsumerName()
{
  static int cnt = 0;
  
  ....
  cnt++;
  ....
}

cnt變量的值會(huì )跟隨著(zhù)函數的調用次而遞增,函數退出后,cnt的值還存在,只是cnt只能在函數中才能被訪(fǎng)問(wèn)。而cnt的內存也只會(huì )在函數第一次被調用時(shí)才會(huì )被分配和初始化,以后每次進(jìn)入函數,都不為static分配了,而直接使用上一次的值。

對于一些被經(jīng)常調用的函數內的常量,最好也聲明成static(參見(jiàn)第12條)

但static的最多的用處卻不在這里,其最大的作用的控制訪(fǎng)問(wèn),在C中如果一個(gè)函數或是一個(gè)全局變量被聲明為static,那么,這個(gè)函數和這個(gè)全局變量,將只能在這個(gè)C文件中被訪(fǎng)問(wèn),如果別的C文件中調用這個(gè)C文件中的函數,或是使用其中的全局(用extern關(guān)鍵字),將會(huì )發(fā)生鏈接時(shí)錯誤。這個(gè)特性可以用于數據和程序保密。

24、函數中的代碼尺寸

一個(gè)函數完成一個(gè)具體的功能,一般來(lái)說(shuō),一個(gè)函數中的代碼最好不要超過(guò)600行左右,越少越好,最好的函數一般在100行以?xún)龋?00行左右的孫函數就差不多了。有證據表明,一個(gè)函數中的代碼如果超過(guò)500行,就會(huì )有和別的函數相同或是相近的代碼,也就是說(shuō),就可以再寫(xiě)另一個(gè)函數。

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

雖然函數的調用會(huì )有一定的開(kāi)銷(xiāo),但比起軟件后期維護來(lái)說(shuō),增加一些運行時(shí)的開(kāi)銷(xiāo)而換來(lái)更好的可維護性和代碼重用性,是很值得的一件事。

25、typedef的使用

typedef是一個(gè)給類(lèi)型起別名的關(guān)鍵字。不要小看了它,它對于你代碼的維護會(huì )有很好的作用。比如C中沒(méi)有bool,于是在一個(gè)軟件中,一些程序員使用int,一些程序員使用short,會(huì )比較混亂,最好就是用一個(gè)typedef來(lái)定義,如:

  typedef char bool;
  
一般來(lái)說(shuō),一個(gè)C的工程中一定要做一些這方面的工作,因為你會(huì )涉及到跨平臺,不同的平臺會(huì )有不同的字長(cháng),所以利用預編譯和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;
  #else
   typedef long long   INT64_T;
  #endif
  
  typedef float      FLOAT32_T;
  typedef char*      STRING_T;
  typedef unsigned char  BYTE_T;
  typedef time_t     TIME_T;
  typedef INT32_T     PID_T;
  
使用typedef的其它規范是,在結構和函數指針時(shí),也最好用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;

于是,當我們用其定義變量時(shí),會(huì )顯得十分易讀。如:

  HostInfo* phinfo;
  RsrcReqHandler* pRsrcHand;
這種方式的易讀性,在函數的參數中十分明顯。

關(guān)鍵是在程序種使用typedef后,幾乎所有的程序中的類(lèi)型聲明都顯得那么簡(jiǎn)潔和清淅,而且易于維護,這才是typedef的關(guān)鍵。

26、為常量聲明宏

最好不要在程序中出現數字式的“硬編碼”,如:

  int user[120];
  
為這個(gè)120聲明一個(gè)宏吧。為所有出現在程序中的這樣的常量都聲明一個(gè)宏吧。比如TimeOut的時(shí)間,最大的用戶(hù)數量,還有其它,只要是常量就應該聲明成宏。如果,突然在程序中出現下面一段代碼,

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

120是什么?為什么會(huì )是120?這種“硬編碼”不僅讓程序很讀,而且也讓程序很不好維護,如果要改變這個(gè)數字,得同時(shí)對所有程序中這個(gè)120都要做修改,這對修改程序的人來(lái)說(shuō)是一個(gè)很大的痛苦。所以還是把常量聲明成宏,這樣,一改百改,而且也很利于程序閱讀。

  #define MAX_USR_CNT 120
  
  for ( i=0; i<MAX_USER_CNT; i++){
    ....
  }

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

有的程序員喜歡為這種變量聲明全局變量,其實(shí),全局變量應該盡量的少用,全局變量不利于封裝,也不利于維護,而且對程序執行空間有一定的開(kāi)銷(xiāo),一不小心就造成系統換頁(yè),造成程序執行速度效率等問(wèn)題。所以聲明成宏,即可以免去全局變量的開(kāi)銷(xiāo),也會(huì )有速度上的優(yōu)勢。

27、不要為宏定義加分號

有許多程序員不知道在宏定義時(shí)是否要加分號,有時(shí),他們以為宏是一條語(yǔ)句,應該要加分號,這就錯了。當你知道了宏的原理,你會(huì )贊同我為會(huì )么不要為宏定義加分號的??匆粋€(gè)例子:

  #define MAXNUM 1024;
這是一個(gè)有分號的宏,如果我們這樣使用:
  half = MAXNUM/2;
  
  if ( num < MAXNUM )
等等,都會(huì )造成程序的編譯錯誤,因為,當宏展開(kāi)后,他會(huì )是這個(gè)樣子的:
  half = 1024;/2;
  
  if ( num < 1024; )
  
是的,分號也被展進(jìn)去了,所以造成了程序的錯誤。請相信我,有時(shí)候,一個(gè)分號會(huì )讓你的程序出現成百個(gè)錯誤。所以還是不要為宏加最后一個(gè)分號,哪怕是這樣:
  #define LINE  "================================="
  
  #define PRINT_LINE printf(LINE)
  #define PRINT_NLINE(n) while ( n-- >0 ) { PRINT_LINE; }
  
都不要在最后加上分號,當我們在程序中使用時(shí),為之加上分號,
  main()
  {
    char *p = LINE;
    PRINT_LINE;
  }
這一點(diǎn)非常符合習慣,而且,如果忘加了分號,編譯器給出的錯誤提示,也會(huì )讓我們很容易看懂的。

28、||和&&的語(yǔ)句執行順序

條件語(yǔ)句中的這兩個(gè)“與”和“或”操作符一定要小心,它們的表現可能和你想像的不一樣,這里條件語(yǔ)句中的有些行為需要和說(shuō)一下:

  express1 || express2
    
先執行表達式express1如果為“真”,express2將不被執行,express2僅在express1為“假”時(shí)才被執行。因為第一個(gè)表達式為真了,整個(gè)表達式都為真,所以沒(méi)有必要再去執行第二個(gè)表達式了。

  express1 && express2

先執行表達式express1如果為“假”,express2將不被執行,express2僅在express1為“真”時(shí)才被執行。因為第一個(gè)表達式為假了,整個(gè)表達式都為假了,所以沒(méi)有必要再去執行第二個(gè)表達式了。

于是,他并不是你所想像的所有的表達式都會(huì )去執行,這點(diǎn)一定要明白,不然你的程序會(huì )出現一些莫明的運行時(shí)錯誤。

例如,下面的程序:

  if ( sum > 100 &&
     ( ( fp=fopen( filename,"a" ) ) != NULL )  {
    
     fprintf(fp, "Warring: it beyond one hundredn");
     ......
  }
  
  fprintf( fp, " sum is %id n", sum );
  fclose( fp );

本來(lái)的意圖是,如果sum > 100 ,向文件中寫(xiě)一條出錯信息,為了方便,把兩個(gè)條件判斷寫(xiě)在一起,于是,如果sum<=100時(shí),打開(kāi)文件的操作將不會(huì )做,最后,fprintf和fclose就會(huì )發(fā)現未知的結果。

再比如,如果我想判斷一個(gè)字符是不是有內容,我得判斷這個(gè)字符串指針是不為空(NULL)并且其內容不能為空(Empty),一個(gè)是空指針,一個(gè)是空內容。我也許會(huì )這樣寫(xiě):

  if ( ( p != NULL ) && ( strlen(p) != 0 ))

于是,如果p為NULL,那么strlen(p)就不會(huì )被執行,于是,strlen也就不會(huì )因為一個(gè)空指針而“非法操作”或是一個(gè)“Core Dump”了。

記住一點(diǎn),條件語(yǔ)句中,并非所有的語(yǔ)句都會(huì )執行,當你的條件語(yǔ)句非常多時(shí),這點(diǎn)要尤其注意。

29、盡量用for而不是while做循環(huán)

基本上來(lái)說(shuō),for可以完成while的功能,我是建議盡量使用for語(yǔ)句,而不要使用while語(yǔ)句,特別是當循環(huán)體很大時(shí),for的優(yōu)點(diǎn)一下就體現出來(lái)了。

因為在for中,循環(huán)的初始、結束條件、循環(huán)的推進(jìn),都在一起,一眼看上去就知道這是一個(gè)什么樣的循環(huán)。剛出學(xué)校的程序一般對于鏈接喜歡這樣來(lái):

  p = pHead;
  
  while ( p ){
    ...
    ...
    p = p->next;
  }

當while的語(yǔ)句塊變大后,你的程序將很難讀,用for就好得多:

  for ( p=pHead; p; p=p->next ){
  ..
  }

一眼就知道這個(gè)循環(huán)的開(kāi)始條件,結束條件,和循環(huán)的推進(jìn)。大約就能明白這個(gè)循環(huán)要做個(gè)什么事?而且,程序維護進(jìn)來(lái)很容易,不必像while一樣,在一個(gè)編輯器中上上下下的搗騰。

30、請sizeof類(lèi)型而不是變量

許多程序員在使用sizeof中,喜歡sizeof變量名,例如:
int score[100];
char filename[20];
struct UserInfo usr[100];

在sizeof這三個(gè)的變量名時(shí),都會(huì )返回正確的結果,于是許多程序員就開(kāi)始sizeof變量名。這個(gè)習慣很雖然沒(méi)有什么不好,但我還是建議sizeof類(lèi)型。

我看到過(guò)這個(gè)的程序:
  pScore = (int*) malloc( SUBJECT_CNT );
  memset( pScore, 0, sizeof(pScore) );
  ...
  
此時(shí),sizeof(pScore)返回的就是4(指針的長(cháng)度),不會(huì )是整個(gè)數組,于是,memset就不能對這塊內存進(jìn)行初始化。為了程序的易讀和易維護,我強烈建議使用類(lèi)型而不是變量,如:

對于score:   sizeof(int) * 100 
對于filename: sizeof(char) * 20 
對于usr:    sizeof(struct UserInfo) * 100 

這樣的代碼是不是很易讀?一眼看上去就知道什么意思了。

另外一點(diǎn),sizeof一般用于分配內存,這個(gè)特性特別在多維數組時(shí),就能體現出其優(yōu)點(diǎn)了。如,給一個(gè)字符串數組分配內存,

char* *p;

p = (char**)calloc( 20*100, sizeof(char) );

p = (char**) calloc ( 20, sizeof(char*) );
for ( i=0; i<20; i++){
  
  p = (char*) calloc ( 100, sizeof(char) );
}

(注:上述語(yǔ)句被注釋掉的是原來(lái)的,是錯誤的,由dasherest朋友指正,謝謝)
為了代碼的易讀,省去了一些判斷,請注意這兩種分配的方法,有本質(zhì)上的差別。

31、不要忽略Warning

對于一些編譯時(shí)的警告信息,請不要忽視它們。雖然,這些Warning不會(huì )妨礙目標代碼的生成,但這并不意味著(zhù)你的程序就是好的。必竟,并不是編譯成功的程序才是正確的,編譯成功只是萬(wàn)里長(cháng)征的第一步,后面還有大風(fēng)大浪在等著(zhù)你。從編譯程序開(kāi)始,不但要改正每個(gè)error,還要修正每個(gè)warning。這是一個(gè)有修養的程序員該做的事。

一般來(lái)說(shuō),一面的一些警告信息是常見(jiàn)的:

1)聲明了未使用的變量。(雖然編譯器不會(huì )編譯這種變量,但還是把它從源程序中注釋或是刪除吧)
2)使用了隱晦聲明的函數。(也許此函數在別的C文件中,編譯時(shí)會(huì )出現這種警告,你應該這之前使用extern關(guān)鍵字聲明這個(gè)函數)
3)沒(méi)有轉換一個(gè)指針。(例如malloc返回的指針是void的,你沒(méi)有把之轉成你實(shí)際類(lèi)型而報警,還是手動(dòng)的在之前明顯的轉換一下吧)
4)類(lèi)型向下轉換。(例如:float f = 2.0; 這種語(yǔ)句是會(huì )報警告的,編譯會(huì )告訴你正試圖把一個(gè)double轉成float,你正在閹割一個(gè)變
量,你真的要這樣做嗎?還是在2.0后面加個(gè)f吧,不然,2.0就是一個(gè)double,而不是float了)
  
不管怎么說(shuō),編譯器的Warning不要小視,最好不要忽略,一個(gè)程序都做得出來(lái),何況幾個(gè)小小的Warning呢?

32、書(shū)寫(xiě)Debug版和Release版的程序

程序在開(kāi)發(fā)過(guò)程中必然有許多程序員加的調試信息。我見(jiàn)過(guò)許多項目組,當程序開(kāi)發(fā)結束時(shí),發(fā)動(dòng)群眾刪除程序中的調試信息,何必呢?為什么不像VC++那樣建立兩個(gè)版本的目標代碼?一個(gè)是debug版本的,一個(gè)是Release版的。那些調試信息是那么的寶貴,在日后的維護過(guò)程中也是很寶貴的東西,怎么能說(shuō)刪除就刪除呢?

利用預編譯技術(shù)吧,如下所示聲明調試函數:

  #ifdef DEBUG
    void TRACE(char* fmt, ...)
    {
      ......
    }
  #else
    #define TRACE(char* fmt, ...)
  #endif

于是,讓所有的程序都用TRACE輸出調試信息,只需要在在編譯時(shí)加上一個(gè)參數“-DDEBUG”,如:

  cc -DDEBUG -o target target.c

于是,預編譯器發(fā)現DEBUG變量被定義了,就會(huì )使用TRACE函數。而如果要發(fā)布給用戶(hù)了,那么只需要把取消“-DDEBUG”的參數,于是所有用到TRACE宏,這個(gè)宏什么都沒(méi)有,所以源程序中的所有TRACE語(yǔ)言全部被替換成了空。一舉兩得,一箭雙雕,何樂(lè )而不為呢?

順便提一下,兩個(gè)很有用的系統宏,一個(gè)是“__FILE__”,一個(gè)是“__LINE__”,分別表示,所在的源文件和行號,當你調試信息或是輸出錯誤時(shí),可以使用這兩個(gè)宏,讓你一眼就能看出你的錯誤,出現在哪個(gè)文件的第幾行中。這對于用C/C++做的大工程非常的管用。
綜上所述32條,都是為了三大目的--

  1、程序代碼的易讀性。
  2、程序代碼的可維護性,
  3、程序代碼的穩定可靠性。
  
有修養的程序員,就應該要學(xué)會(huì )寫(xiě)出這樣的代碼!這是任何一個(gè)想做編程高手所必需面對的細小的問(wèn)題,編程高手不僅技術(shù)要強,基礎要好,而且最重要的是要有“修養”!

好的軟件產(chǎn)品絕不僅僅是技術(shù),而更多的是整個(gè)軟件的易維護和可靠性。
  
軟件的維護有大量的工作量花在代碼的維護上,軟件的Upgrade,也有大量的工作花在代碼的組織上,所以好的代碼,清淅的,易讀的代碼,將給大大減少軟件的維護和升級成本。
本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
c/c++程序員面試
從單片機初學(xué)者邁向單片機工程師
C語(yǔ)言預處理命令詳解
C++編程修養
編程修養(二)
typeof關(guān)鍵字
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久