• <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>

            那誰的技術博客

            感興趣領域:高性能服務器編程,存儲,算法,Linux內核
            隨筆 - 210, 文章 - 0, 評論 - 1183, 引用 - 0
            數據加載中……

            CGL開發手記之二--CGL中的數據類型

            為了做到能操作所有類型的數據,我參看了幾個類似的C語言的庫,基本上就是兩種做法:一是使用宏,二是使用void*指針。最后我選擇了后者,原因很簡單,我不是一個很推崇在代碼中大量使用宏的人,一方面覺得這樣作會讓代碼的可讀性降低,另一方面我也確實不是寫宏的高手。

            在CGL中,有以下的幾個typedef都把void*定義為某種類型:
            typedef void* container_t;
            typedef void* point_t;
            typedef void* data_t;

            分別作一個解釋,container_t表示的是指向容器的指針,point_t表示的是通用指向某容器的指針,不論是指向數組成員的指針還是一個鏈表結點的指針都可以"泛化"的表示為"pos_t",而data_t表示的是存放數據的指針,之所以要對同樣可以表示為是void*的指針分三個類型的typedef,目的是為了在代碼中一目了然,看到類型的名字就能知道是作什么用的了。

            container_t的含義很好理解,現在對后面兩種類型作一下解釋。

            原本pos_t不叫pos_t的,而是被定義為iter_t,因為在STL中迭代器其實就是一個行為很像指針的東東,可以解引用,可以遞增指向下一個元素,遞減指向前一個元素,等等。但是需要注意的時候,由于C++中可以重載操作符,如*,++,--這樣的操作符都可以被重載以至于一個iterator的行為看上去和一個普通的指針沒有什么區別。但是在CGL中,是完全采用的C語言實現的,沒有辦法做到重載這些操作符,所以我專門提供了一個叫做iteraotr_t的結構體,里面有函數指針成員可以實現以上這些重載操作符所需要作的事情(后面會有專門的一節來講述這個結構體以及CGL中迭代器的設計),所以如果有一個類型為iter_t一個類型為iterator_t會不會讓人混淆呢?至少我偶爾回頭看我的代碼的時候是會弄混的,因此我決定把iter_t更名為pos_t也就是位置的意思。

            data_t用于保存存放數據的指針,這里有幾個問題需要交待一下。首先是這樣作的弊端,雖然這樣避免前面提到的大量使用宏的缺點,但是卻浪費了存儲的空間以及會帶來一些使用上的不方便。先說浪費了存儲空間,以往存放一個數據只需要一個與該數據相同大小的空間就可以了,但是現在還需要多使用一個data_t指針指向分配好的空間,無形之中浪費了一個指針的空間。再說使用的不方便,以往處理數據的時候如果沒有特別的要求可以直接傳值,而現在必須傳指針,因為CGL的函數不認什么int,double,char類型,只處理指針。換句話說,假如f是CGL中的一個函數,如果要調用傳入一個整型參數5,你必須這樣作:
            int nVal = 5;
            f(&nVal);
            而一般傳值就可以做到的調用是f(5)就可以了,這樣會造成使用上的不方便。
            至于數據的賦值,我采用的C庫中memcpy函數,只要傳入指向數據的指針和數據的尺寸就可以,比較數據是否相等則采用C庫中的memcmp函數,所需要知道的參數和memcpy一樣,而當需要比較數據的大小時,這個比較頭疼,因為C庫中沒有根據指針和數據的大小進行比較的函數,我在后面會解釋我現在處理此類問題的辦法。

            再來說說其他的兩個typedef:
            typedef char* base_t;
            typedef char  bool_t;
            最后的一個bool_t很好理解,就是一般的bool型嘛,之所以用char很簡單,char類型所需要的字節數最少,省空間。而base_t這個類型的含義是一個系統中最基本的數據類型,或者可以這么理解,別的數據類型所占有的字節數都可以表示為這個類型的算術操作,以上的言語也許晦澀了一些,我用例子來說明。
            看CGL中一個函數的實現:
            static point_t cgls_iter_advance(piterator_t pIter, size_t n)
            {
                base_t tTmp;

                CGL_ASSERT(
            NULL != pIter);
                CGL_ASSERT(
            0 <= n);

                tTmp 
            = (base_t)(pIter->tPoint);
                pIter
            ->tPoint = tTmp + pIter->nValSize * n;
                return pIter
            ->tPoint;
            }
            這個函數的作用是把迭代器pIter中保存的指向容器中數據的指針tPoint向前移動n個位置,大家知道指針的移動和它所指向的數據類型的大小有密切的關系,換句話說一個指針向前走n個位置所要移動的字節數為n * 它所指向的數據的尺寸,在上面的函數中,tPoint這個指針所指向的數據的尺寸存放在pIter的成員變量nValSize中,你也許會問直接使用sizeof(*tPoint)不就可以得到這個數值了么?別忘了我們前面說過所有的指針類型都是void*,而對void*指針是不能進行解引用操作的,所以我們需要一個變量來存放數據的尺寸。
            注意到函數中的兩個操作:
             tTmp = (base_t)(pIter->tPoint);
             pIter->tPoint = tTmp + pIter->nValSize * n;
            結合著base_t的定義,可以解釋為把void*指針tPoint強制轉化為char*,而tPoint向前走的位置為tTmp +  nValSize*n,對于tTmp而言,它的類型是base_t也即是char*,sizeof(char) = 1,因此采用char*來保存以及進行指針的加減操作是最自然的操作,只要我們知道需要前進的步數(n),每部的幅度(nValSize),就可以通過把指針強制轉化為base_t也就是char*來達到我們所要到達的位置。

            以上,是我對目前CGL中幾個typedef的解釋??梢钥吹降氖牵O計中總是存在著這樣那樣的折中,很多地方的處理也是不完美的,我選擇的是不向宏妥協而是自己對指針進行處理和操作。

            posted on 2007-05-02 00:59 那誰 閱讀(786) 評論(0)  編輯 收藏 引用 所屬分類: CGL

            久久精品人妻中文系列| 国产精品va久久久久久久| 91久久九九无码成人网站| 精品免费久久久久久久| 色诱久久久久综合网ywww | 热久久这里只有精品| 精品久久久久久无码专区| 久久青青草原亚洲av无码app | 88久久精品无码一区二区毛片| 久久精品夜夜夜夜夜久久| 久久精品麻豆日日躁夜夜躁| 中文字幕久久久久人妻| 国产精品99久久免费观看| 国产精品天天影视久久综合网| 精品久久久久久久无码| 亚洲综合精品香蕉久久网97| 久久精品国产亚洲av瑜伽| 久久人人爽人人爽人人片av麻烦 | 三上悠亚久久精品| 久久99精品久久久久婷婷| segui久久国产精品| 久久久久久极精品久久久| 久久综合久久综合亚洲| 日韩精品久久久肉伦网站| 久久电影网一区| 亚洲日本久久久午夜精品| 久久精品国产99久久久古代| 久久se精品一区精品二区| 欧美国产精品久久高清| 日韩精品久久久久久久电影蜜臀| 久久精品国产免费| 久久精品免费全国观看国产| 国产V亚洲V天堂无码久久久| 观看 国产综合久久久久鬼色 欧美 亚洲 一区二区 | 亚洲婷婷国产精品电影人久久| 久久青青草原精品影院| 国产精品成人99久久久久 | 久久99国产精品久久久| 久久伊人五月天论坛| 国产精品久久波多野结衣| 久久久国产视频|