未經許可,不的轉載
  版權歸屬高雷個人
  聯絡方式:
  email:gaolei57521@gamil.com
  qq:38929568

由於本人剛剛編寫C程式不久,文章中不當的地方難免會有,望大家批評指正,我會第一時間修改!

  最近搞MTK遊戲開發,使用的是C語言,所以想研究一下C語言的開發情況,通過論壇,或者搜尋到一些高手的文章,給我的啟示不小!結合以前的Java經驗,想總結一下,高手都是如何寫程式的…

  我的文章不會講述一個C語言學習的過程,也不會面面俱到講述C語言,我只針對學習過C語言,或者有一定程式設計基礎,在寫程式碼的時候總是不自信地想知道別人是如何編寫的!

  我希望通過閱讀本文,能夠使初級程式設計師迅速成長為高階程式設計師!

  1.如何釋放記憶體

  很簡單free();就ok啦!

  C語言中,malloc,realloc,calloc,strdup等等都是動態從堆裡面分配的記憶體,他不會自動釋放。在這裡需要記錄分配的地址,以便以後釋放。如果不進行釋放,會造成記憶體洩漏。在堆記憶體申請的記憶體是需要程式設計師管理的,系統不會主動回收,可以通過free()函式回收。通常的商業程式碼都有很多指標,或者指標的指標,結構體裡包含指標型別的成員,那麼這些指標該如何管理,才不至於出錯呢?

  例如 Role *pRole = (Role *)malloc( sizeof(Role) );

  釋放指標

  free( pRole );

  pRole = NULL;

釋放指標後,將指標指回0點,如果你覺得每次都要寫2行程式碼太麻煩了,可以定一個巨集
 

 

如果行用一個函式來釋放並且達到同樣的目的該如何寫呢?

 

  1. //釋放指標型別資料
  2. void freePointer(void *p)
  3. {
  4. if( p != NULL )
  5. {
  6. free( p );
  7. p = NULL;
  8. }
  9. }

 

這麼寫是不行的,因為指標p是通過copy方式將實參的值copy過來,

free( p ); 沒問題,可以把指標p所指的記憶體釋放,但取無法把指標指向NULL,這是因為形參的地址和實參的地址是不同的!

 

  1. //釋放指標型別資料
  2. void freePointer(void **p)
  3. {
  4. if( *p != NULL )
  5. {
  6. free( *p );
  7. *p = NULL;
  8. }
  9. }

 

這樣修改就可以了,但這要求實引數是一個指標的地址

使用的時候要這麼用

freePointer( (void *)(&pRole) );

這樣用著依然不爽,強制型別轉換有些編譯器是必須的,比如我用的,

基本不是,取指標地址還是必須的!總之給人不直觀,不清爽的感覺,

如果換成

FREE( pRole );

就好多了!

  1.1如果釋放一個帶有指標的結構體指標

 

  1. //角色資料型別
  2.  
  3. typedef struct
  4. {
  5.   char* name; //動作檔案的名字
  6. }ACT; //動畫
  7.  
  8.  
  9. typedef struct
  10. {
  11.   ACT* body; //身體動作資料
  12. }Role;

 

建立角色物件,我想通過一個方法

 

  1. // 建立 角色資料物件
  2. Role* creatRole( const char* roleName, uint8 weaponId );
  3. // 回收 角色資料物件
  4. void destroyRole( Role *role);

 

那麼建立的時候確實可以得到一個角色的指標

Role *pRole =creatRole( “hero”, 0 );

釋放的時候如果想達到呼叫

destroyRole(pRole );

後,pRole 指向NULL,該如何做呢?

通過freePointer()方法給我們的教訓可以知道,

 

  1. /* 回收 角色資料物件 */
  2. void destroyRole( Role *role )
  3. {
  4.   if( role == NULL )
  5.   return;
  6.  
  7.   destroyAct( role->body );//是否結構體內的指標,有幾個就要釋放幾個
  8.    free( role );
  9.  
  10.   role = NULL;
  11. }

 

其中的role = NULL;是不能把實參pRole 指向NULL的!

如果我們向前面提到那樣使用巨集,或者獲取指標地址的形式似乎可以解決,但其實沒必要那麼麻煩,通常的做法是手動指向NULL

destroyRole(pRole );

pRole = NULL;

為什麼要有pRole = NULL;這句呢?因為最上層的結構體物件通常都是需要程式知道是否

為空,或者非空,另外指回原點,也對除錯有好處,單獨free()物件,在除錯的時候是看不出來的!

另外還要提到一點

 

  1. Role* creatRole( const char* roleName, uint8 weaponId )
  2.  
  3. {
  4.  
  5. Role role;
  6.  
  7. role.body= (ACT*)malloc( sizeof(ACT) );
  8.  
  9. return &role;
  10.  
  11. }

 

這個方法是絕對不可取的,因為role是函式內部的臨時變數,在函式結束的時候會被系統回收的,隨意&role這個地方的資料將被系統重新使用。

在C語言程式設計中並不是所有指標都需要指回NULL的,如果你願意都指回NULL更好,但至少應該把一組指標的源頭指回NULL,這才能防止程式出錯,另外就是把源頭指回NULL之前要確保該指標下面的全部指標都已經被回收了!否則就記憶體洩漏了!

PS.未經許可 不得轉載!