0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線(xiàn)課程
  • 觀(guān)看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

嵌入式開(kāi)發(fā)中C語(yǔ)言位結(jié)構(gòu)體有哪些用途詳細(xì)分析講解

Q4MP_gh_c472c21 ? 來(lái)源:未知 ? 2019-02-23 09:07 ? 次閱讀

嵌入式開(kāi)發(fā)中,經(jīng)常需要表示各種系統(tǒng)狀態(tài),位結(jié)構(gòu)體的出現(xiàn)大大方便了我們,尤其是在進(jìn)行一些硬件層操作和數(shù)據(jù)通信時(shí)。但是在使用位結(jié)構(gòu)體的過(guò)程中,是否深入思考一下它的相關(guān)屬性?是否真正用到它的便利性,來(lái)提高系統(tǒng)效率?

下面將進(jìn)行一些相關(guān)實(shí)驗(yàn)(這里以項(xiàng)目開(kāi)發(fā)中的實(shí)際代碼為例):

1.位結(jié)構(gòu)體類(lèi)型設(shè)計(jì)

[cpp]view plaincopyprint?

1.//datastructureexceptfornumberstructure

2.typedefstructsymbol_struct

3.{

4.uint_32SYMBOL_TYPE:5;//datatype,havetheaffecton"datadisplaytype"

5.uint_32reserved_1:4;

6.

7.uint_32SYMBOL_NUMBER:7;//effectivedatanumberinoneelement

8.uint_32SYMBOL_ACTIVE:1;//symbolactivestatus

9.

10.uint_32SYMBOL_INDEX:8;//dataindexinnorflash,resultisrelatedto"xxx_BASE_ADDR"

11.uint_32reserved_2:8;

12.

13.}SYMBOL_STRUCT,_PTR_SYMBOL_STRUCT_PTR;

分析:這里定義了一個(gè)位結(jié)構(gòu)體類(lèi)型SYMBOL_STRUCT,那么用該類(lèi)型定義的變量都哪些屬性呢?

看下面運(yùn)行結(jié)果:

WORDS是定義的另一個(gè)外層類(lèi)型定義封裝,可以把它當(dāng)作變量來(lái)看待。WORDS變量里前5個(gè)數(shù)據(jù)域的地址都是0x1ffff082c,而reserved_2的地址0x1fff0830,緊接著的PressureState變量是0x1fff0834。

開(kāi)始以為:reserved_1和SYMBOL_TYPE不在一個(gè)地址上,因?yàn)樗麄?+4共9位,超過(guò)了1個(gè)字節(jié)地址,但實(shí)際他們共用首地址了;而且reserved_2只定義了8位,竟然實(shí)際占用了4個(gè)字節(jié)(0x1fff0834 - 0x1fff0830),我本來(lái)是想讓他占用1個(gè)字節(jié)的。WORDS整體占了8個(gè)字節(jié)(0x1fff0834 - 0x1fff082c),設(shè)計(jì)時(shí)分析占用5個(gè)字節(jié)

(SYMBOL_TYPE 1個(gè);reserved_1 1個(gè);SYMBOL_NUMBER+SYMBOL_ACTIVE 1個(gè);SYMBOL_INDEX 1個(gè);reserved_2 1個(gè))。

uint_32 reserved_2 : 8; 占用4個(gè)字節(jié),估計(jì)是uint_32在起作用,而這里寫(xiě)的8位,只是我使用的有效位數(shù),另外24位空閑,如果在下面再定義一個(gè)uint_32 reserved_3 : 8,地址也是一樣的,都是以u(píng)int_32為單位取地址。

同理,上面的5個(gè)變量,共用一個(gè)地址就不足為奇了。而且有效位的分配不是連續(xù)進(jìn)行的,例如SYMBOL_TYPE+reserved_1 共9位,超過(guò)了一個(gè)字節(jié),索性系統(tǒng)就分配兩個(gè)字節(jié)給他們,每人一個(gè);SYMBOL_NUMBER+SYMBOL_ACTIVE 共8位,一個(gè)字節(jié)就能搞定。

2、修改數(shù)據(jù)結(jié)構(gòu),驗(yàn)證上述猜想

[cpp]view plaincopyprint?

1.//datastructureexceptfornumberstructure

2.typedefstructsymbol_struct

3.{

4.uint_8SYMBOL_TYPE:5;//datatype,havetheaffecton"datadisplaytype"

5.uint_8reserved_1:4;

6.

7.uint_8SYMBOL_NUMBER:7;//effectivedatanumberinoneelement

8.uint_8SYMBOL_ACTIVE:1;//symbolactivestatus

9.

10.uint_8SYMBOL_INDEX:8;//dataindexinnorflash,resultisrelatedto"xxx_BASE_ADDR"

11.uint_8reserved_2:8;

12.

13.}SYMBOL_STRUCT,_PTR_SYMBOL_STRUCT_PTR;

14.

地址數(shù)據(jù)如下:

當(dāng)換成uint_8后,可以看到地址空間占用大大減小,reserved_2只占用1個(gè)字節(jié)(0x1fff069f - 0x1fff069e),其他變量也都符合上面的結(jié)論猜想。但是,注意看上面黃色和紅色的語(yǔ)句,總感覺(jué)有些勉強(qiáng),那么我又會(huì)想,前兩個(gè)變量數(shù)據(jù)域是9位,那么他們實(shí)際上是不是真正的獨(dú)立呢?雖然在uint_8上面他們是不同的地址,在uint_32的時(shí)候是不是也是不同的地址空間呢?

3、分析結(jié)構(gòu)體內(nèi)部的數(shù)據(jù)域是否連續(xù),看下圖及結(jié)果

本來(lái)假設(shè):由前2次試驗(yàn)的結(jié)論,一共占用8個(gè)字節(jié),節(jié)空間占用:(2+4)+(4+4)+(2+2+4)+(2+2)+(6)??墒?,實(shí)際效果并不是想的那樣。實(shí)際只占用了4個(gè)字節(jié),系統(tǒng)并沒(méi)有按照預(yù)想的方式,為RESERVED變量分配4個(gè)字節(jié)。

分析:

這些數(shù)據(jù)域,整體相加一共32位,占用4個(gè)字節(jié)(不考慮數(shù)據(jù)對(duì)齊問(wèn)題)。而實(shí)際確實(shí)是占用了4個(gè)字節(jié),唯一的原因就是:這些數(shù)據(jù)域以緊湊的方式鏈接,沒(méi)有任何空閑位。實(shí)際是不是這樣呢?

看下圖和結(jié)果:

這里為了驗(yàn)證是否緊湊鏈接,用到了一個(gè)union數(shù)據(jù),后面會(huì)講到用union不會(huì)對(duì)數(shù)據(jù)組織方式有任何影響,看實(shí)際與上次的一樣,也能分析出來(lái)。

主要是分析第2和第3個(gè)數(shù)據(jù)域是否緊密鏈接的。OBJECT_ACTIVE_PRE賦值0b00001111,NUMBER_ACTIVE賦值0b00000101,其他變量都是0,看到WORD數(shù)值0b1011111000000。分析WORD數(shù)據(jù),可以看到這款MCU還是小端格式(高位數(shù)據(jù)在高端,低位數(shù)據(jù)在低端,這里不對(duì)大小端進(jìn)行討論),斷開(kāi)數(shù)據(jù)變成(0)10111 11000000,正好是0101+1111,OBJECT_ACTIVE_PRE數(shù)據(jù)域,跨越了兩個(gè)字節(jié),并不是剛開(kāi)始設(shè)想的那樣。這就印證了上面的緊密鏈接的結(jié)論,也符合數(shù)據(jù)結(jié)果輸出。

4、再次實(shí)驗(yàn),分析數(shù)據(jù)是否緊密鏈接,看下圖和結(jié)果

可以看到,RESERVED數(shù)據(jù)域已經(jīng)不再屬于4個(gè)地址空間內(nèi)了(0x1fff0518 - 0x1fff051b),但是他們整體加起來(lái)還是32個(gè)位域。這說(shuō)明數(shù)據(jù)中間肯定有“空隙”存在了,空隙在哪?看一下NUMBER_STATE,如果緊密的話(huà)它應(yīng)該跟NUMBER_ACTIVE在同一個(gè)字節(jié)地址上,可是他們并不在一塊,“空隙”就存在這里。

這兩個(gè)結(jié)構(gòu)體有什么不一樣?數(shù)據(jù)類(lèi)型不一致,一個(gè)是uint_32,一個(gè)是uint_8。綜上所述:數(shù)據(jù)類(lèi)型影響的是編譯器在分配物理空間時(shí)的大小單位,uint_32是以4個(gè)字節(jié)為單位,而后面的位域則是指在已經(jīng)分配好的物理空間內(nèi)部再緊湊的方式分配數(shù)據(jù)位,當(dāng)物理空間不能滿(mǎn)足位域時(shí),那么系統(tǒng)就再次以一定大小單位進(jìn)行物理空間分配,這個(gè)單位就是上面提到的uint_8或者uint_32。

舉例:上面uint_32時(shí),這些位域不管是不是在一個(gè)字節(jié)地址上,如果能夠緊湊的分配在一個(gè)4字節(jié)空間大小上,就直接緊湊分配。如果不能則繼續(xù)分配(總空間超過(guò)4字節(jié)),則再次以4字節(jié)空間分配,并把新的位域建立在新的地址空間上(條目1上的就是)。當(dāng)uint_8時(shí),很明顯如果位域不能緊湊的放在一個(gè)字節(jié)空間上,那么就從新分配新的1字節(jié)空間大小,道理是一樣的。

5、結(jié)構(gòu)體組合、共用體組合是否影響上述結(jié)論

可以看到,系統(tǒng)并沒(méi)有因?yàn)槲唤Y(jié)構(gòu)體上面有uint_4的4字節(jié)變量或者共用體類(lèi)型,就改變分配策略把位域都擠到4字節(jié)之內(nèi),看來(lái)他們是沒(méi)有什么實(shí)質(zhì)性聯(lián)系的。這里把uint_32改成uint_8,或者把位結(jié)構(gòu)體也替換掉,經(jīng)我試驗(yàn)證明,都是沒(méi)有任何影響的。

總結(jié)

1、在操作位結(jié)構(gòu)體時(shí),要關(guān)注變量的位域是否在一個(gè)變量類(lèi)型(uint_32或者uint_8)上,判斷占用空間大小

2、除了位域,還要關(guān)注變量定義類(lèi)型,因?yàn)榫幾g器空間分配始終是按類(lèi)型分配的,位域只是指出了有效位(小于類(lèi)型占用空間),而且如果位域大于類(lèi)型空間,編譯器直接報(bào)錯(cuò)(如 uint_8 test :15,可自行實(shí)驗(yàn))。

3、這兩個(gè)因素都影響變量占用空間大小,具體可以結(jié)合調(diào)試窗口,通過(guò)地址分配分析判斷

4、最重要的一點(diǎn):上面的所有結(jié)果,都是基于我自己的CodeWarrior10.2和MQX3.8分析出來(lái)的,不同的編譯環(huán)境和操作系統(tǒng),都可能會(huì)有不同的結(jié)果;而且即便是環(huán)境相同,編譯器的配置和優(yōu)化選項(xiàng)都有可能影響系統(tǒng)處理結(jié)果。結(jié)論并不重要,主要想告訴大家這一塊隱藏陷阱,在以后處理類(lèi)似問(wèn)題時(shí),要注意分析避讓并掌握方法。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀(guān)點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • mcu
    mcu
    +關(guān)注

    關(guān)注

    146

    文章

    16802

    瀏覽量

    349370
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7581

    瀏覽量

    135590
  • 嵌入式開(kāi)發(fā)

    關(guān)注

    18

    文章

    1012

    瀏覽量

    47431

原文標(biāo)題:嵌入式開(kāi)發(fā)中,C語(yǔ)言位結(jié)構(gòu)體用途詳解

文章出處:【微信號(hào):gh_c472c2199c88,微信公眾號(hào):嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    詳細(xì)分析嵌入式Linux系統(tǒng)啟動(dòng)流程

    嵌入式Linux專(zhuān)題(一)已經(jīng)對(duì)嵌入式Linux系統(tǒng)的架構(gòu)及啟動(dòng)流程了初步的介紹,本文將詳細(xì)分析
    發(fā)表于 11-05 09:25

    嵌入式開(kāi)發(fā)為什么選擇C語(yǔ)言?

    1、嵌入式開(kāi)發(fā)為什么選擇C語(yǔ)言?(面試題?。。。?b class='flag-5'>嵌入式開(kāi)發(fā)操作系統(tǒng)是核心,需要移植,并在上層和底層做開(kāi)
    發(fā)表于 12-15 07:45

    嵌入式系統(tǒng)高級(jí)C語(yǔ)言編程

    嵌入式系統(tǒng)高級(jí)C語(yǔ)言編程》將以實(shí)際項(xiàng)目中的代碼作實(shí)例來(lái)進(jìn)行介紹,詳細(xì)分析嵌入式系統(tǒng)開(kāi)發(fā)中程序
    發(fā)表于 10-27 16:36 ?4696次閱讀

    嵌入式開(kāi)發(fā)就業(yè)前景分析_嵌入式領(lǐng)域的職業(yè)發(fā)展方向

    嵌入式開(kāi)發(fā)技術(shù)在物聯(lián)網(wǎng)領(lǐng)域應(yīng)用最為廣泛,適合于各個(gè)領(lǐng)域,主要應(yīng)用于消費(fèi)類(lèi)電子行業(yè)。嵌入式開(kāi)發(fā)的入門(mén)門(mén)檻還是比較高的。那么嵌入式開(kāi)發(fā)就業(yè)前景怎么樣呢?嵌入式領(lǐng)域的職業(yè)發(fā)展方向是什么?本文
    發(fā)表于 01-29 14:09 ?1.8w次閱讀

    嵌入式開(kāi)發(fā)語(yǔ)言哪些_最全面嵌入式開(kāi)發(fā)語(yǔ)言概述

    嵌入式開(kāi)發(fā)語(yǔ)言哪些?嵌入式開(kāi)發(fā)的入門(mén)門(mén)檻還是比較高的,不僅要懂較底層軟件,對(duì)軟件專(zhuān)業(yè)水平要求較高,而且必須懂得硬件的工作原理,嵌入式系統(tǒng)應(yīng)
    發(fā)表于 01-29 14:47 ?9732次閱讀
    <b class='flag-5'>嵌入式開(kāi)發(fā)</b><b class='flag-5'>語(yǔ)言</b><b class='flag-5'>有</b>哪些_最全面<b class='flag-5'>嵌入式開(kāi)發(fā)</b><b class='flag-5'>語(yǔ)言</b>概述

    嵌入式開(kāi)發(fā)要學(xué)什么嵌入式開(kāi)發(fā)的一些入門(mén)教材推薦

    本文檔的主要內(nèi)容詳細(xì)介紹的是嵌入式開(kāi)發(fā)要學(xué)什么嵌入式開(kāi)發(fā)的一些入門(mén)教材推薦資料免費(fèi)下載教材包括了:ARM嵌入式項(xiàng)目開(kāi)發(fā)
    發(fā)表于 01-10 14:46 ?27次下載
    <b class='flag-5'>嵌入式開(kāi)發(fā)</b>要學(xué)什么<b class='flag-5'>嵌入式開(kāi)發(fā)</b>的一些入門(mén)教材推薦

    嵌入式開(kāi)發(fā)通常采用哪種編程語(yǔ)言

    目前在嵌入式開(kāi)發(fā)領(lǐng)域比較常見(jiàn)的編程語(yǔ)言C,另外C++、Python、JavaScript等語(yǔ)言也可以進(jìn)行
    發(fā)表于 06-18 16:59 ?1.6w次閱讀

    什么是嵌入式開(kāi)發(fā)?為什么用C語(yǔ)言作為開(kāi)發(fā)語(yǔ)言?

    內(nèi)部做開(kāi)發(fā)的,而操作系統(tǒng)所有的內(nèi)核都是C語(yǔ)言所編寫(xiě)的,所以說(shuō)在嵌入式開(kāi)發(fā)的過(guò)程也選擇C
    發(fā)表于 11-02 18:50 ?12次下載
    什么是<b class='flag-5'>嵌入式開(kāi)發(fā)</b>?為什么用<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>作為<b class='flag-5'>開(kāi)發(fā)</b><b class='flag-5'>語(yǔ)言</b>?

    嵌入式開(kāi)發(fā)培訓(xùn)學(xué)什么?嵌入式開(kāi)發(fā)板知識(shí)講解

    嵌入式開(kāi)發(fā)就是指在嵌入式操作系統(tǒng)下進(jìn)行開(kāi)發(fā),一般常用的系統(tǒng)WinCE,ucos,vxworks,linux,android等。另外,用c,
    發(fā)表于 11-02 20:21 ?16次下載
    <b class='flag-5'>嵌入式開(kāi)發(fā)</b>培訓(xùn)學(xué)什么?<b class='flag-5'>嵌入式開(kāi)發(fā)</b>板知識(shí)<b class='flag-5'>講解</b>

    嵌入式開(kāi)發(fā)為什么選擇C語(yǔ)言作為開(kāi)發(fā)語(yǔ)言

    了解嵌入式開(kāi)發(fā)的朋友們都非常的清楚其核心的開(kāi)發(fā)語(yǔ)言C語(yǔ)言,C
    發(fā)表于 11-03 09:21 ?17次下載
    <b class='flag-5'>嵌入式開(kāi)發(fā)</b>為什么選擇<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>作為<b class='flag-5'>開(kāi)發(fā)</b><b class='flag-5'>語(yǔ)言</b>?

    嵌入式為什么選擇C語(yǔ)言作為開(kāi)發(fā)語(yǔ)言

    了解嵌入式開(kāi)發(fā)的朋友們都非常的清楚其核心的開(kāi)發(fā)語(yǔ)言C語(yǔ)言,C
    發(fā)表于 11-03 14:06 ?15次下載
    <b class='flag-5'>嵌入式</b>為什么選擇<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>作為<b class='flag-5'>開(kāi)發(fā)</b><b class='flag-5'>語(yǔ)言</b>?

    嵌入式開(kāi)發(fā)為什么選擇C語(yǔ)言?它有哪些特點(diǎn)?

    眾所周知,C語(yǔ)言嵌入式開(kāi)發(fā)占據(jù)著十分重要的地位,為什么嵌入式開(kāi)發(fā)要選擇C
    的頭像 發(fā)表于 01-04 09:56 ?1148次閱讀
    <b class='flag-5'>嵌入式開(kāi)發(fā)</b><b class='flag-5'>中</b>為什么選擇<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>?它有哪些特點(diǎn)?

    c語(yǔ)言嵌入式開(kāi)發(fā)

    電子發(fā)燒友網(wǎng)站提供《c語(yǔ)言嵌入式開(kāi)發(fā).zip》資料免費(fèi)下載
    發(fā)表于 11-17 14:11 ?2次下載
    <b class='flag-5'>c</b><b class='flag-5'>語(yǔ)言</b><b class='flag-5'>嵌入式開(kāi)發(fā)</b>

    嵌入式C語(yǔ)言結(jié)構(gòu)特點(diǎn)

    嵌入式開(kāi)發(fā)既有底層硬件的開(kāi)發(fā)又涉及上層應(yīng)用的開(kāi)發(fā),即涉及系統(tǒng)的硬件和軟件,C語(yǔ)言既具有匯編
    的頭像 發(fā)表于 11-24 16:16 ?586次閱讀
    <b class='flag-5'>嵌入式</b><b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>的<b class='flag-5'>結(jié)構(gòu)</b>特點(diǎn)

    嵌入式開(kāi)發(fā)前景怎么樣?

    嵌入式開(kāi)發(fā)前景非常廣闊,這主要得益于物聯(lián)網(wǎng)、人工智能、大數(shù)據(jù)等技術(shù)的快速發(fā)展,以及嵌入式系統(tǒng)在各個(gè)領(lǐng)域的廣泛應(yīng)用。以下是對(duì)嵌入式開(kāi)發(fā)前景的詳細(xì)分析
    的頭像 發(fā)表于 07-10 09:00 ?2067次閱讀
    <b class='flag-5'>嵌入式開(kāi)發(fā)</b>前景怎么樣?