• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 16,  comments - 34,  trackbacks - 0

            本文概括敘述了一篇老文的內容,并且總結對malloc返回值的3種轉型方式,(相對于原文)更全面的總結其各自的應用范圍。

            1. 原文內容
            2. 對malloc的3種轉型方式
            3. 各自的應用范圍

             


             

            以前有篇文章叫《C/C++ 誤區 —— 強制轉換 malloc() 的返回值》。
            文章大致內容是:

            1. malloc函數在<stdlib.h> 或者 <cstdlib>頭文件中,而不是<malloc.h>。


            2. 由于C語言最初沒有void類型,所以是使用char*來代表通用指針。

            /* the old declaration of malloc */
            char* malloc(size_t size);

            char* p = malloc(size * sizeof(*p) );
            /* 可以, 不需要轉型 */

            T1
            * p1 = malloc(size1 * sizeof(*p1) );
            /* (T1!=char不可以,char*不能隱式轉換成T1*  */

            T2
            * p2 = (T2*)malloc(size2 * sizeof(*p2) );
            /* (T2!=char) 可以,顯示類型轉換 */

             

            3.C語言后來引入了void類型,就可以使用void*代表通用指針,同時規定void*可以隱式轉換任意指針類型。

            /* the new declaration of malloc */
            void* malloc(size_t size);

            char* p = malloc(size * sizeof(*p) );
            /* 仍然可以,void*可以隱式轉換到任意指針類型 */

            T1
            * p1 = malloc(size1 * sizeof(*p1) );
            /* 現在可以,void*可以隱式轉換到任意指針類型 */

            T2
            * p2 = (T1*)malloc(size2 * sizeof(*p2) );
            /* 仍然可以,但不再必須 */


            4. 在引入了void之后的C語言中,再使用強制轉換是畫蛇添足,同時影響代碼維護。
            并且說這是一個C/C++的誤區

             



            原文概述完畢,開始說本文章的內容:
            對malloc返回值的轉型,大致有以下三種方式:

             

            1. 僅在C中

            /* legal only in C */

            /* 新頭文件 */
            T
            * p = malloc(size * sizeof(*p) ); /* T!=void */


            /* 舊頭文件 */

            T* p = (T*)malloc(size* sizeof(*p) ); /* T!=void */


            2.僅在C++中
            C++天然支持void,但是不允許void*隱式轉換到任意類型指針,需要static_cast。

            // 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++中

            /* legal in both C and C++ */
            /* legal in both new  and old header */
            T
            * p = (T*)malloc(size * sizeof(*p) );

             



            第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

            posted on 2009-03-06 10:16 OwnWaterloo 閱讀(4124) 評論(4)  編輯 收藏 引用

            FeedBack:
            # re: 對malloc的返回值應該如何轉型
            2009-03-17 19:01 | C++ Beginner
            學長,問您個很基礎的問題,C風格的強制類型轉換會觸發對應的構造函數么?static_cast和reinterpret_cast會么?另外這兩個轉換符具體做了些什么?  回復  更多評論
              
            # re: 對malloc的返回值應該如何轉型
            2009-03-17 21:10 | OwnWaterloo
            @C++ Beginner
            強制轉換都不會觸發構造函數。

             
            static_cast用于隱式轉換過程,如:
            short s; int i;
            = s; //可以,向更寬整數類型進行隱式轉換。
            = i; //警告,向更窄整數類型轉換。
            = static_cast<short>(i); //過程,明確表明代碼作者的意圖,警告消除。
             
            base* b; derived* d;
            = d; // 可以,向上轉型,隱式轉換。
            = b; // 錯誤,向下轉型,不允許。
            = static_cast<derived*>(b); // 可以,向上轉型的過程。但不保證正確
             
            object* o; void* p;
            = o; // 可以,任何指針類型都可以隱式轉換到void*
            = p; // 過程是錯誤,除非
            = static_cast<object*>(o); // 可以,但不保證正確
             
             
            reinterpret_cast用于整數和指針之間,無繼承關系的指針之間的轉換。
            按照其二進制表示,重新解釋(Re-Interpret),如:
            T* p; intptr_t i;
            = reinterpret_cast<intptr_t>(p);
            // 將p的地址,解釋成一個整數。
            = reinterpret_cast<T*>(i);
            // 將i的值,解釋成一個指向T的指針。
             
            T1* p1; T2* p2;
            p1 
            = reinterpret_cast<T1*>(p2);
            // 將p2中保存的地址的值,復制到p1。
            // 因為p1是T1*類型的指針,以后對p1的操作,將按T1*來解釋

            // 另外一種方式:
            p1 = static_cast<T1*>static_cast<void*>(p2) );
              回復  更多評論
              
            # re: 對malloc的返回值應該如何轉型
            2009-03-17 22:33 | C++ Beginner
            學長,我以碰到過到一個ansi字符串轉CString類型的問題,當時發現可以直接這樣來:

            char a[100] = "123";
            CString str = (CString)a;

            我當初認為是這樣強轉觸發了CString的構造函數,構造了一個CString temp變量,然后賦給str。因為我當時查看反匯編時,發現它call了一個很長很奇怪的函數,并且看下來確實是構造函數。

            看了學長的解釋,我忽然發現難道自己一直以來對強制類型轉換理解錯了?額……到底是怎么回事?學長賜教!  回復  更多評論
              
            # re: 對malloc的返回值應該如何轉型
            2009-03-17 22:56 | OwnWaterloo
            @C++ Beginner
            如果一個用戶自定義類型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";


            上面說錯了,這種轉換確實會調用構造函數。  回復  更多評論
              
            <2025年6月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            常用鏈接

            留言簿(8)

            隨筆檔案(16)

            鏈接

            搜索

            •  

            積分與排名

            • 積分 - 198340
            • 排名 - 134

            最新隨筆

            最新評論

            閱讀排行榜

            評論排行榜

            人妻精品久久久久中文字幕69 | 久久伊人亚洲AV无码网站| 免费国产99久久久香蕉| 国产巨作麻豆欧美亚洲综合久久 | 91精品国产综合久久精品| 国产91色综合久久免费分享| 777久久精品一区二区三区无码| 久久99精品九九九久久婷婷| 亚洲色欲久久久综合网东京热| 国产精品美女久久久久网| 亚洲精品美女久久久久99小说| 成人综合伊人五月婷久久| 香蕉久久影院| 国产AⅤ精品一区二区三区久久 | 久久久久久A亚洲欧洲AV冫| 亚洲精品无码成人片久久| 久久se这里只有精品| 国产亚洲精品美女久久久| 久久综合一区二区无码| 色综合久久综合网观看| 久久国产欧美日韩精品| 日韩亚洲国产综合久久久| 久久99精品国产| 久久久亚洲欧洲日产国码aⅴ | 国内精品九九久久精品 | 成人午夜精品无码区久久| 亚洲欧美国产日韩综合久久| 热久久国产精品| 久久亚洲国产中v天仙www| 99久久精品毛片免费播放| 久久久精品国产sm调教网站 | 99久久777色| 久久99精品久久只有精品| 中文精品久久久久人妻不卡| 婷婷国产天堂久久综合五月| 午夜精品久久久久9999高清| 一本大道久久香蕉成人网| 狠狠色丁香婷婷久久综合| 亚洲欧美一区二区三区久久| 久久精品成人欧美大片| 色偷偷88888欧美精品久久久|