• <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 閱讀(4107) 評論(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";


            上面說錯了,這種轉換確實會調用構造函數。  回復  更多評論
              
            <2013年1月>
            303112345
            6789101112
            13141516171819
            20212223242526
            272829303112
            3456789

            常用鏈接

            留言簿(8)

            隨筆檔案(16)

            鏈接

            搜索

            •  

            積分與排名

            • 積分 - 197918
            • 排名 - 133

            最新隨筆

            最新評論

            閱讀排行榜

            評論排行榜

            亚洲第一极品精品无码久久| 亚洲国产精品热久久| 久久久久亚洲AV无码观看| 97久久超碰国产精品旧版| 午夜精品久久久久久影视riav| 久久国产亚洲精品麻豆| 中文字幕无码精品亚洲资源网久久 | 久久国产亚洲精品无码| 久久久精品国产亚洲成人满18免费网站| 国产精品久久久久久久久软件 | 97久久综合精品久久久综合| 久久www免费人成看国产片| 99久久免费国产精品| 日韩精品久久久久久久电影蜜臀| 99久久这里只精品国产免费| 精品国产91久久久久久久| 亚洲精品国产综合久久一线| 综合久久一区二区三区| 久久婷婷久久一区二区三区| 国产精品青草久久久久福利99 | 久久久久久免费视频| 蜜桃麻豆www久久| 欧美亚洲色综久久精品国产| 亚洲精品tv久久久久| 久久夜色撩人精品国产| 久久久久亚洲国产| 青青久久精品国产免费看| 人妻系列无码专区久久五月天| 亚洲精品国产成人99久久| 国产精品视频久久| 久久91精品国产91久久小草| 久久亚洲精品国产精品| 久久精品国产亚洲AV无码偷窥| 伊人久久大香线焦AV综合影院 | 99久久精品免费看国产免费| 久久国产精品-久久精品| 久久亚洲国产午夜精品理论片| 国内精品久久久久影院一蜜桃 | 久久久久久极精品久久久| 久久精品99无色码中文字幕| 久久免费视频6|