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

            久久人妻少妇嫩草AV蜜桃| 久久青青草原综合伊人| 国产精品久久久久天天影视| 女同久久| 久久久久综合中文字幕 | 激情综合色综合久久综合| 久久精品人人做人人爽电影蜜月| 久久久久久精品久久久久| 午夜视频久久久久一区 | 久久99热精品| 久久免费小视频| 久久九九久精品国产| 亚洲v国产v天堂a无码久久| 国产农村妇女毛片精品久久| 国产精品成人99久久久久91gav| 国产精品久久久久久福利漫画| 国产一级做a爰片久久毛片| 久久夜色tv网站| 久久国产免费直播| 无码八A片人妻少妇久久| 国产亚洲精品久久久久秋霞| 日产精品久久久一区二区| 999久久久无码国产精品| 91久久香蕉国产熟女线看| 久久亚洲国产精品五月天婷| 性做久久久久久久久浪潮| 狠狠综合久久AV一区二区三区| 国产精品99久久久精品无码 | 国产精品一久久香蕉产线看| 国产精品xxxx国产喷水亚洲国产精品无码久久一区 | 日本福利片国产午夜久久| 亚洲国产精品成人AV无码久久综合影院| 久久影院久久香蕉国产线看观看| 久久中文字幕人妻熟av女| 国产精品久久久久久| 久久精品国产只有精品66| 一本久久知道综合久久| 亚洲一本综合久久| 无码日韩人妻精品久久蜜桃| 成人亚洲欧美久久久久| 亚洲va中文字幕无码久久|