memset()的效率以及源碼分析

文章來源:http://blog.csdn.net/hackbuteer1/article/details/7343189

void *memset(void *s, int ch, size_t n);

作用:將s所指向的某一塊內存中的每個字節的內容全部設置爲ch指定的ASCII值, 塊的大小由第三個參數指定,這個函數通常爲新申請的內存做初始化工作。
不知道有沒有像我一樣把memset當作萬能的初始化工具,例如:
int arr[n];
memset(arr,1,n*sizeof(int));
這樣得到的arr數組一定不是全0,而是16843009,下面解釋原因。
首先,變量類型的本質只是標誌從某一內存地址開始讀取的位數,強制轉換就是改變讀取位數的大小。

下面來看memset的實現:(代碼來自《C標準庫》P398)

  1. void *(memset) (void *s,int c,size_t n)  
  2. {  
  3.     const unsigned char uc = c;  
  4.     unsigned char *su;  
  5.     for(su = s;0 < n;++su,--n)  
  6.         *su = uc;  
  7.     return s;  
  8. }  
第3行把int類型的c轉換成unsigned char類型,意味着截去c的高24位,只保留低8位。第4行把s當作unsigned char*類型,也就是說su中的每一個元素按8位計算。
現在來看看文章開頭的那個代碼會做什麼。
c的二進制 : 00000000000000000000000000000001(32位)
1、c轉換爲unsigned char 後:00000001(8位)
2、將指針su(unsigned char類型)的每一元素(8位)賦值爲00000001,循環4n次。
3、memset()結束後,arr的每個元素按照int類型讀取,讀出來的就是1000000010000000100000001,十進制就是16843009。

不過如果是memset(arr,0,n*sizeof(int));的話可以使用,因爲32位都是0

再來說memset()的效率問題。使用memset函數與將上面的函數代碼寫在自己的程序裏是不一樣的,C標準庫中的memset對Cache的利用做了優化,具體的在《C專家編程》151頁有解釋(其實是我沒看懂),這裏給出測試:
  1. #include <string.h>  
  2. #define MAXSIZE 100000  
  3.   
  4. int main()  
  5. {  
  6.     char arr[MAXSIZE];  
  7.     for(int i=0;i<10000;i++)  
  8.     {  
  9.         memset(arr,'0',sizeof(arr));  
  10. //        for(int j=0;j<MAXSIZE;j++)  
  11. //            arr[0] = '0';  
  12.     }  
  13.     return 0;  
  14. }  
程序裏的註釋部分與memset行分別使用,結果是使用memset的程序運行時間大約爲0.1s,而用for循環的程序要3s多。
綜上:memset()可以用在字符數組的初始化以及類似於memset(arr,0,n*sizeof(int));的情況,效率比手動賦值要高的多。


發佈了33 篇原創文章 · 獲贊 3 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章