• <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>
            franksunny的個人技術(shù)空間
            獲得人生中的成功需要的專注與堅持不懈多過天才與機會。 ——C.W. Wendte

            C/C++ 結(jié)構(gòu)體的一個高級特性 ―― 指定成員的位數(shù)

            ?

            在大多數(shù)情況下,我們一般這樣定義結(jié)構(gòu)體:

            struct student

            {

            ????????????? ? unsigned int sex;

            ????????????? unsigned int age;

            };

            對于一般的應(yīng)用,這已經(jīng)能很充分地實現(xiàn)數(shù)據(jù)了的 封裝

            但是,在實際工程中,往往碰到這樣的情況:那就是要用一個基本類型變量中的不同的位表示不同的含義。譬如一個 cpu 內(nèi)部的標(biāo)志寄存器,假設(shè)為 16 bit ,而每個 bit 都可以表達不同的含義,有的表示結(jié)果是否為 0 ,有的表示是否越界等等。這個時候我們用什么數(shù)據(jù)結(jié)構(gòu)來表達這個寄存器呢?

            答案還是結(jié)構(gòu)體!

            為達到此目的,我們要用到結(jié)構(gòu)體的高級特性,那就是在基本成員變量的后面添加“ : 數(shù)據(jù)位數(shù)”組成新的結(jié)構(gòu)體:

            struct xxx

            {

            ????????????? 成員 1 類型成員 1 : 成員 1 位數(shù) ;

            ?????? ????? ? 成員 2 類型成員 2 : 成員 2 位數(shù) ;

            ?????? ????? ? 成員 3 類型成員 3 : 成員 3 位數(shù) ;

            };

            基本的成員變量就會被拆分!這個語法在初級編程中很少用到,但是在高級程序設(shè)計中不斷地被用到!例如:

            struct student

            {

            ????????????? ? unsigned int sex : 1;

            ????????????? unsigned int age : 15;

            };

            上述結(jié)構(gòu)體中的兩個成員 sex age 加起來只占用了一個 unsigned int 的空間(假設(shè) unsigned int 16 位)。

            基本成員變量被拆分后,訪問的方法仍然和訪問沒有拆分的情況是一樣的,例如:

            struct student sweek;

            sweek.sex = MALE;// 這里的 MALE 只能是 0 1 ,值不能大于 1

            sweek.age = 20;

            雖然拆分基本成員變量在語法上是得到支持的,但是并不等于我們想怎么分就怎么分,例如下面的拆分顯然是不合理的:

            struct student

            {

            ????????????? ??? unsigned int sex : 1;

            ????????????? ? unsigned int age : 12;

            };

            這是因為 1+12 = 13 ,不能再組合成一個基本成員,不能組合成 char int 或任何類型,這顯然是不能 自圓其說 的。

            在拆分基本成員變量的情況下,我們要特別注意數(shù)據(jù)的存放順序,這還與 CPU Big endian 還是 Little endian 來決定。 Little endian Big endian CPU 存放數(shù)據(jù)的兩種不同順序。對于整型、長整型等數(shù)據(jù)類型, Big endian 認為第一個字節(jié)是最高位字節(jié)(按照從低地址到高地址的順序存放數(shù)據(jù)的高位字節(jié)到低位字節(jié));而 Little endian 則相反,它認為第一個字節(jié)是最低位字節(jié)(按照從低地址到高地址的順序存放數(shù)據(jù)的低位字節(jié)到高位字節(jié))。

            我們定義 IP 包頭結(jié)構(gòu)體為:

            struct iphdr {

            #if defined(__LITTLE_ENDIAN_BITFIELD)

            ?????? __u8?????? ihl:4,

            ?????? ?????? version:4;

            #elif defined (__BIG_ENDIAN_BITFIELD)

            ?????? __u8?????? version:4,

            ???? ?????? ihl:4;

            #else

            #error?????? "Please fix <asm/byteorder.h>"

            #endif

            ?????? __u8?????? tos;

            ?????? __u16?????? tot_len;

            ?????? __u16?????? id;

            ?????? __u16?????? frag_off;

            ?????? __u8?????? ttl;

            ?????? __u8?????? protocol;

            ?????? __u16?????? check;

            ?????? __u32?????? saddr;

            ?????? __u32?????? daddr;

            ?????? /*The options start here. */

            };

            Little endian 模式下, iphdr 中定義:

            ?????? __u8?????? ihl:4,

            ?????? ?????? version:4;

            其存放方式為:

            1 字節(jié)低 4 ?ihl

            1 字節(jié)高 4 ?version IP 的版本號)

            若在 Big endian 模式下還這樣定義,則存放方式為:

            1 字節(jié)低 4 ?version IP 的版本號)

            1 字節(jié)高 4 ?ihl

            這與實際的 IP 協(xié)議是不匹配的,所以在 Linux 內(nèi)核源代碼中, IP 包頭結(jié)構(gòu)體的定義利用了宏:

            #if defined(__LITTLE_ENDIAN_BITFIELD)

            #elif defined (__BIG_ENDIAN_BITFIELD)

            #endif

            來區(qū)分兩種不同的情況。

            由此我們總結(jié)全文的主要觀點:

            1 ?????? C/C++ 語言的結(jié)構(gòu)體支持對其中的基本成員變量按位拆分;

            2 ?????? 拆分的位數(shù)應(yīng)該是合乎邏輯的,應(yīng)仍然可以組合為基本成員變量;

            要特別注意拆分后的數(shù)據(jù)的存放順序,這一點要結(jié)合具體的 CPU 的結(jié)構(gòu)。

            ?

            ?

            ?

            ?

            該文是由宋寶華處轉(zhuǎn)載而來的,筆者以前從未知道結(jié)構(gòu)體還可以這樣用法,筆者做過嘗試,再 VC 下用過的感受有兩點

            1、????????????? 結(jié)構(gòu)體按位拆分時,雖然宋兄提醒不能拆分如文中紅色背景顯示的情況,但是本人試過,并非是不可以的,而且如果 CPU 支持 32 的話,顯然文中的以 16 位來分配的話也是沒有達到要求的。

            2、????????????? 按位拆分時字節(jié)數(shù)目問題,我們先看兩例

            ?????? struct student1

            ?????? {

            ????????????? unsigned char sex : 1;

            ????????????? unsigned int? no : 5;

            ????????????? char??????? ??age : 7;

            ????????????? int????????? grade : 10;

            ?????? };

            ?

            ????????????? struct student2

            ?????? {

            ????????????? unsigned char sex : 1;

            ????????????? char??????? ? ?age : 7;

            ????????????? unsigned int ?no : 5;???????????

            ????????????? int????????? grade : 10;

            ?????? };

            以上兩例中雖然意思并不大,但是如果按 int 2 字節(jié) 16 char 1 字節(jié) 8 位來劃分內(nèi)存的話,那么 student1 占用了 6 字節(jié)共 48 位,但是實際使用了 23 位,另外 25 位沒定義,而 student2 占用了 3 字節(jié)共 24 位,但是實際使用也是 23 位。這個過程,我把它總結(jié)為前后變量的類型不一致時,字節(jié)就重新分配。

            3、????????????? 賦值過程中數(shù)據(jù)編碼問題。還看兩例

            ?????? student1 ss;

            ?????? ss.age = 255;

            ?????? student2 st;

            ?????? st.age= 191;

            ss.age 的值為 -1 ,而 st.age 的值為 63 ,其實 255 11111111 ,因為是 7 位,所以采用截斷方式,變成 1111111 ,又因為 age 是有符號的變量,所以根據(jù)負數(shù)的編碼規(guī)則賦值 255 時得到的結(jié)果就是 -1 。在這里采用了截斷的方式,為止正確賦值時一定不能大于位數(shù)編碼值。

            以上是個人學(xué)習(xí)宋兄文章的小小實踐小結(jié),歡迎大家給出更理論的總結(jié)。原文請查看 http://blog.donews.com/21cnbao/archive/2006/10/07/1054807.aspx

            posted on 2006-10-20 00:05 frank.sunny 閱讀(6660) 評論(7)  編輯 收藏 引用 所屬分類: C/C++學(xué)習(xí)和實踐

            FeedBack:
            # re: C/C++結(jié)構(gòu)體的一個高級特性――指定成員的位數(shù)
            2006-10-20 13:31 | guest
            位域,已經(jīng)是一個很古老的特性了  回復(fù)  更多評論
              
            # re: C/C++結(jié)構(gòu)體的一個高級特性――指定成員的位數(shù)
            2006-10-20 20:34 | 木葉流水
            student2 占用了 3 字節(jié)?
            unsigned char sex : 1;
            char age : 7; 分別占一個字節(jié) unsigned int no : 5;
            int grade : 10;兩個加起來占一個字節(jié)是吧
            一共三個字節(jié)  回復(fù)  更多評論
              
            # re: C/C++結(jié)構(gòu)體的一個高級特性――指定成員的位數(shù)
            2006-10-20 21:04 | frank.sunny
            非常感謝樓上不留名的大俠指點,我還算是個新手,謝謝你一語道破了,這只是一個“位域”概念,本人搜索了一下這一概念,發(fā)現(xiàn)有一個人總結(jié)的還比較可以的
            總結(jié)如下:
            使用位域的主要目的是壓縮存儲,其大致規(guī)則為:
            1) 如果相鄰位域字段的類型相同,且其位寬之和小于類型的sizeof大小,則后面的字段將緊鄰前一個字段存儲,直到不能容納為止;
            2) 如果相鄰位域字段的類型相同,但其位寬之和大于類型的sizeof大小,則后面的字段將從新的存儲單元開始,其偏移量為其類型大小的整數(shù)倍;
            3) 如果相鄰的位域字段的類型不同,則各編譯器的具體實現(xiàn)有差異,VC6采取不壓縮方式,Dev-C++采取壓縮方式;
            4) 如果位域字段之間穿插著非位域字段,則不進行壓縮;
            5) 整個結(jié)構(gòu)體的總大小為最寬基本類型成員大小的整數(shù)倍。


            樓上木葉流水兄,看過這個總結(jié)不知道是否有更清晰的了解啊,可以看他網(wǎng)頁
            http://blog.csdn.net/jiyucn/archive/2006/07/01/862085.aspx

              回復(fù)  更多評論
              
            # re: C/C++結(jié)構(gòu)體的一個高級特性――指定成員的位數(shù)
            2006-10-25 20:17 | 清風(fēng)雨
            這個特性,在現(xiàn)在內(nèi)存相對充足來說,基本是無所謂的;除非你做嵌入式開發(fā)或許有點用(不是做這個的,不了解)。
            另外,他會成員的訪問低效;而且加上內(nèi)存對齊,這里節(jié)省的空間又被編譯器為了性能填充的無用字節(jié)給浪費了(當(dāng)然,你可以設(shè)置不對齊)。
            在現(xiàn)在,這個特性,真的是很古老哦(而且基本無用),也算不上高級啦!
            當(dāng)然,你作為了解了解一下也是好的。
              回復(fù)  更多評論
              
            # re: C/C++結(jié)構(gòu)體的一個高級特性――指定成員的位數(shù)
            2006-10-26 09:39 | frank.sunny
            @清風(fēng)雨
            其實題目是沿用原作者的,我也是學(xué)習(xí)用的,他本人就是搞嵌入式的,我覺得這個可以搞懂些變量底層的東西

            謝謝大俠關(guān)心啊,呵呵  回復(fù)  更多評論
              
            # re: C/C++結(jié)構(gòu)體的一個高級特性――指定成員的位數(shù)
            2008-07-01 11:41 | Eagles
            學(xué)習(xí)了!!!!  回復(fù)  更多評論
              
            # re: C/C++結(jié)構(gòu)體的一個高級特性――指定成員的位數(shù)
            2009-05-27 15:57 | Alec C.
            位域在嵌入式開發(fā)中還是很有用的,特別是涉及到底層協(xié)議的時候  回復(fù)  更多評論
              

            常用鏈接

            留言簿(13)

            隨筆分類

            個人其它博客

            基礎(chǔ)知識鏈接

            最新評論

            閱讀排行榜

            評論排行榜

            久久精品免费大片国产大片| 久久只有这里有精品4| 国产精品免费看久久久| 国色天香久久久久久久小说| 久久精品无码一区二区三区| 国内精品久久人妻互换| 久久综合九色综合97_久久久| 欧美精品一区二区精品久久 | 亚洲AV无一区二区三区久久| 狠狠色丁香久久婷婷综合_中| 久久se精品一区二区影院| 久久久久99精品成人片三人毛片 | 性欧美丰满熟妇XXXX性久久久 | 国产精品福利一区二区久久| 亚洲国产精品久久久久婷婷软件| 精品久久久久久国产免费了| 无码乱码观看精品久久| 久久久久高潮综合影院| 欧美va久久久噜噜噜久久| 精品国产一区二区三区久久| 九九热久久免费视频| 久久精品国产99久久久古代| 欧美一区二区三区久久综| 伊人久久大香线焦综合四虎| 久久久久久久亚洲精品| 久久精品亚洲AV久久久无码| 久久久久亚洲av无码专区喷水| 国产午夜福利精品久久| 久久伊人五月丁香狠狠色| 99久久无码一区人妻a黑| 久久夜色精品国产亚洲av| 亚洲国产精品无码久久久秋霞2| 9999国产精品欧美久久久久久| 中文字幕无码久久精品青草| 久久99精品久久久久婷婷| 热综合一本伊人久久精品| 精品久久久久久久无码 | 亚洲精品乱码久久久久66| 激情久久久久久久久久| 国产A级毛片久久久精品毛片| 久久精品视频免费|