本文歸納敘述了一篇老文的內容,而且總結對malloc返回值的3種轉型方式,(相對於原文)更全面的總結其各自的應用範圍。
1. 原文內容
2. 對malloc的3種轉型方式
3. 各自的應用範圍html
之前有篇文章叫《C/C++ 誤區 —— 強制轉換 malloc() 的返回值》。
文章大體內容是:
1. malloc函數在<stdlib.h> 或者 <cstdlib>頭文件中,而不是<malloc.h>。web
2. 因爲C語言最初沒有void類型,因此是使用char*來表明通用指針。函數
3.C語言後來引入了void類型,就可使用void*表明通用指針,同時規定void*能夠隱式轉換到任意指針類型。
spa
4. 在引入了void以後的C語言中,再使用強制轉換是多此一舉,同時影響代碼維護。
而且說這是一個C/C++的誤區。指針
1. 僅在C中orm
/* legal only in C */
htm
/* 新頭文件 */
T* p = malloc(size * sizeof(*p) ); /* T!=void */blog
/* 舊頭文件 */繼承
2.僅在C++中
C++自然支持void,可是不容許void*隱式轉換到任意類型指針,須要static_cast。ci
// legal only in C++
// 新頭文件
T* p = static_cast<T*>( malloc(size * sizeof(*p) ));
// 舊頭文件(目前還有這種編譯器嗎?)
T* p = reinterpret_cast<T*>( malloc(size * sizeof(*p) ));
// 固然在C++中應該考慮
T* p = new T[size];
// 或者
std::vector<T> p(size);
// 但這不是文章討論重點
3.在C/C++中
第1種對新頭文件的轉型方式,如同代碼第1行所說,僅在C編譯器中合法。
由於C++不支持void*到其餘指針類型的隱式轉換。
因此,原文章說這是C/C++的誤區,並不許確。
這僅僅是(引入void類型以後的)C語言中的「非必須」的動做,是不是誤區,還有待考量。
第2種對新舊頭文件的轉型方式,代碼第1行也說了,僅在C++編譯器中合法。
由於C編譯器不認識static_cast或者reinterpret_cast。
第3種,是一種中庸的寫法。
如同代碼第1行所說:此代碼不管是在C仍是C++編譯器,不管是新頭文件仍是舊頭文件,都是合法的代碼。是可移植性最好的代碼。
由於代碼中使用的(C風格的)轉型、malloc——C/C++都支持。
因此,這種寫法並不必定是誤區或者多此一舉。
由於代碼的做者也許比原文章的做者對移植性(C和C++的新舊編譯器)考慮更多。
一個排版比較好的原文轉載連接
http://programmingart.blog.51cto.com/213782/43503
學長,問您個很基礎的問題,C風格的強制類型轉換會觸發對應的構造函數麼?static_cast和reinterpret_cast會麼?另外這兩個轉換符具體作了些什麼?
若是一個用戶自定義類型C, 有一個能夠經過單個類型爲T的參數進行調用的構造函數, 那麼,該構造函數就定義了一個T到C的轉換。 若是該構造函數是explicit的,T到C的轉換是顯式轉換。 若是該構造函數不是explicit,T到C的轉換是隱式轉換。 例如: class string { char* content_; explicit string(const char* source,int length=-1) :content_(0) { if (length==-1) length = static_cast<int>(strlen(source)); content_ = new char[length+1]; strcpy(source,content_); } }; 這個構造函數能夠經過單個參數調用(第2個參數有默認值),因此這個構造函數定義了一個 const char* 到 string 的轉換。 若是有explicit,那麼該轉換必須是顯式轉換: string s = static_cast<string>("hello"); 若是沒有explict,該轉換能夠是隱式轉換: string s = "hello"; 上面說錯了,這種轉換確實會調用構造函數。