在編程過程中,在大量的情況下需要使用memset()函數對內存進行置零初始化除了這裡說的memset()其實很多函數,比如snprintf()、strncpy()等都可以借用這裡談到的方法),以下三種情況是在工作中經常在這方面碰到的錯誤,大部分錯誤是因為疏忽而造成的。
例1
例2
#define DIGEST_LEN 17例3
dll_node_t *p_node = malloc (sizeof (dll_node_t));
下面示例了如何采用一般化的方法更正上面的三種錯誤。
例1修訂1
例2修訂1
#define DIGEST_LEN 17例3修訂1
dll_node_t *p_node = malloc (sizeof (dll_node_t));
需要思考的是,如何在工作中盡可能的避免這類“低級”錯誤。雖然可以通過采用code review的方式增加錯誤的檢出率,但這種效果並不好。更為好一點的方法是程序員養成一定的編程習慣,比如采用這裡將要主張的sizeof()方法就能顯著地降低這類錯誤。下面示例了如何采用sizeof()來更正錯誤。
例1修訂2
例2修訂2
#define DIGEST_LEN 17例3修訂2
dll_node_t *p_node = malloc (sizeof (dll_node_t));
這裡所說的采用sizeof()規避錯誤的方法其背後的思想是什麼呢?人的大腦是注定要出錯的,如果在大腦中存有處理同一事務的大量規則或根本沒有規則,那麼往往在處理這一事務時更容易出錯。采用memset()函數對內存初始化就屬於容易出錯的一類事務,因為在指定實際被初始化內存的大小時,一般化的方法是需要根據被初始化內存的上下文來決定傳遞給memset()函數內存大小的具體值。如果采用sizeof()來獲取所需初需化內存的大小並將其固化成編程習慣,那麼就不容易出錯。
對於前面的第一和第二種錯誤,只需要將數組當作sizeof()的參數,而不用關心數組在定義時的大小到底是多少。即使因為需要而更改目標數組的大小,sizeof()仍會返回更改後的實際數組的大小,而不需要對memset()函數的調用做任何的手動更改。對於第三種錯誤,方法是相類似的,只不過要采用sizeof(*xxx)的形式,其中xxx是目標指針變量,比如前面第三個例子中的p_node。
注意到采用sizeof()方法的共性了嗎?都是以需要初始化的目標變量作為sizeof()的參數的,而不是以目標變量的類型或是宏作為其參數,這種方式使得寫出來的程序更加不容易出錯。采用sizeof()方法,對於獲取被初始化內存的大小簡化為只有兩條規則:
1)如果目標變量是一個數組,則采用sizeof(xxx)的格式獲取內存大小,其中的xxx是指數組變量名,顯然這個數組變量可以是嵌套在另一個數據結構中的。
2)如果目標變量是一個數據結構的指針,則采用sizeof(*xxx)獲取內存大小,其中的xxx則是指數據結構指針變量名,而不是數據結構類型。
最後一個問題是,采用sizeof()會降低程序的性能嗎?不會!因為sizeof()是在程序編譯時由編譯器進行計算並最終得出一個數字的,是一個靜態的行為而不是運行時行為。
本文出自 “至簡李雲” 博客,請務必保留此出處http://yunli.blog.51cto.com/831344/227130