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

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

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

如何設(shè)計只有數(shù)據(jù)字段的結(jié)構(gòu)體

開關(guān)電源芯片 ? 來源:程序喵大人 ? 作者:程序喵大人 ? 2021-08-23 09:37 ? 次閱讀

之前寫過一篇《如何設(shè)計一個C++的類》,今天這里繼續(xù)聊聊如何設(shè)計結(jié)構(gòu)體,注意本文不介紹在C++中結(jié)構(gòu)體和類具體有什么區(qū)別,本文所說的結(jié)構(gòu)體是指只有數(shù)據(jù)字段不帶任何函數(shù)的那種結(jié)構(gòu)體。

當(dāng)創(chuàng)建結(jié)構(gòu)體的實例時,結(jié)構(gòu)體的數(shù)據(jù)成員會按其聲明的順序連續(xù)存儲。然而,這個聲明的順序也是有學(xué)問的,順序不同結(jié)構(gòu)體的大小可能有很大差別,數(shù)據(jù)成員的訪問性能也可能會有很大區(qū)別!

這里涉及一個概念:內(nèi)存對齊。關(guān)于內(nèi)存對齊我之前寫過一篇文章:《內(nèi)存對齊》,這里不深入討論,只是簡單介紹一下。

大多數(shù)編譯器會對齊數(shù)據(jù)成員,會以四舍五入地址方式來優(yōu)化數(shù)據(jù)的訪問,如下表所示。

0c708e52-02f8-11ec-9bcf-12bb97331649.jpg

這種內(nèi)存對齊可能會在成員大小混合的結(jié)構(gòu)體中產(chǎn)生未使用字節(jié)的空洞。

例如:

struct S {

short int a; // 2字節(jié)

// 6個空洞

double b; // 8

int d; // 4

// 4個空洞

};

S ArrayOfStructures[100];

這里,在a和b之間有6個未使用的字節(jié),因為b必須從一個能被8整除的地址開始。

最后還有4個未使用的字節(jié)空洞。這樣做的原因是,數(shù)組中S的下一個實例必須從一個能被8整除的地址開始,以便將其b成員以8對齊。

然而,如果改變一下結(jié)構(gòu)體中數(shù)據(jù)成員聲明的順序,通過將最小的成員放在最后,未使用的字節(jié)數(shù)可以減少到2:

struct S {

double b; // 8

int d; // 4

short int a; // 2

// 2個空洞

};

S ArrayOfStructures[100];

這種重新排序使結(jié)構(gòu)體變小了8個字節(jié),那整個數(shù)組則變小了800個字節(jié)。

在此特性上,類和結(jié)構(gòu)體相同。通過重新排序數(shù)據(jù)成員,結(jié)構(gòu)體對象和類對象通??梢宰兊酶 H绻愔辽儆幸粋€虛成員函數(shù),則在第一個數(shù)據(jù)成員之前或最后一個成員之后會有一個指向虛函數(shù)表的指針。該指針在32位系統(tǒng)中為4字節(jié),在64位系統(tǒng)中為8字節(jié)。

如果不確定結(jié)構(gòu)體或它的每個成員有多大,可以使用sizeof操作符進行一些測試。sizeof操作符返回的值包括對象末尾的任何未使用的字節(jié)(內(nèi)存對齊后的字節(jié)數(shù))。

還有一個知識點:

如果數(shù)據(jù)成員相對于結(jié)構(gòu)體或類開頭的偏移量小于128,則訪問數(shù)據(jù)成員的代碼會更加緊湊,因為該偏移量可以使用8位有符號的數(shù)字來表示。如果相對于結(jié)構(gòu)體或類的開頭的偏移量是128字節(jié)或更多,那么偏移量必須表示為一個32位數(shù)字(指令集在8位到32位之間沒有偏移量)。例如:

struct S {

int a[100]; // 400

int b; // 4

int read() { return b; }

};

b成員的偏移量是400。任何通過指針或成員函數(shù)訪問b字段的代碼都需要將偏移量編碼為32位數(shù)字。如果交換a和b,則兩者都可以通過編碼為8位有符號數(shù)字的偏移量來訪問,或者根本不需要偏移量。

這會使代碼更緊湊,方便更有效地使用代碼緩存。因此,建議在結(jié)構(gòu)或類聲明中,大數(shù)組和其他大對象排在最后,最常用的數(shù)據(jù)成員排在前面。如果不能在前128個字節(jié)內(nèi)包含所有數(shù)據(jù)成員,則將最常用的成員放在前128個字節(jié)中。

通過上面兩個小知識點可以使得將結(jié)構(gòu)體設(shè)計的更小,訪問數(shù)據(jù)成員的速度更快,但是這有時往往會犧牲一些可讀性,比如這種結(jié)構(gòu)體:

struct S {

int deskA;

double deskB;

bool deskC;

int chairA;

double chairB;

bool chairC;

};

可能這樣修改后結(jié)構(gòu)體會更小:

struct S {

int deskA;

int chairA;

double deskB;

double chairB;

bool deskC;

bool chairC;

};

但是我們一般情況下貌似希望同類的字段放在一起,這樣代碼可讀性更高一些,易于讀懂代碼。至于這種結(jié)構(gòu)體具體需不需要重新排序,那就需要大家自己權(quán)衡啦。

小總結(jié):

注意內(nèi)存對齊;

128是個檻,常用的數(shù)據(jù)成員可考慮放在前128字節(jié)中,不常用的或大的數(shù)據(jù)成員可考慮放在后面;

注重性能優(yōu)化的同時也需要權(quán)衡一下代碼的可讀性。

打完收工。

責(zé)任編輯:haq

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

    關(guān)注

    38

    文章

    7520

    瀏覽量

    164086
  • 內(nèi)存
    +關(guān)注

    關(guān)注

    8

    文章

    3041

    瀏覽量

    74177
  • 結(jié)構(gòu)體
    +關(guān)注

    關(guān)注

    1

    文章

    130

    瀏覽量

    10860

原文標(biāo)題:如何設(shè)計結(jié)構(gòu)體

文章出處:【微信號:gh_3980db2283cd,微信公眾號:開關(guān)電源芯片】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    LDC1000 Frequency Data只有最低數(shù)據(jù)有數(shù)據(jù)其他2位都是0x00,為什么?

    Frequency Data只有最低數(shù)據(jù)有數(shù)據(jù)其他2位都是0x00,我想問下我這問題出在哪里?我的參數(shù)設(shè)置: RpMAX=0x13;//21.547 RpMIN=0x3d; //1.347
    發(fā)表于 01-06 07:33

    ADS5547, DAC8822時序圖上只有數(shù)據(jù)在寄存器之間轉(zhuǎn)換的時序,難道更新速率只和數(shù)據(jù)在寄存器之間轉(zhuǎn)換時間有關(guān)嗎?

    ADS5547, DAC8822時序圖上只有數(shù)據(jù)在寄存器之間轉(zhuǎn)換的時序,難道更新速率只和數(shù)據(jù)在寄存器之間轉(zhuǎn)換時間有關(guān)嗎?
    發(fā)表于 12-20 07:28

    ADS7953SDBTR上電時16個通道中,只有4個通道有數(shù)據(jù),其余12個通道無數(shù)據(jù),怎么解決?

    請教一下,我現(xiàn)在有用一個16通道的模數(shù)轉(zhuǎn)換器ADS7953SDBTR,使用過程中出現(xiàn)了一個問題,第一次上電的時候只有4個通道有數(shù)據(jù),其它12個通道沒有數(shù)據(jù),然后掉電重啟,16個通道都正常了,檢測了
    發(fā)表于 12-06 07:26

    結(jié)構(gòu)成員的順序會影響結(jié)構(gòu)的大小嗎

    相同的結(jié)構(gòu)成員,如果把順序調(diào)整一下,會不會影響結(jié)構(gòu)的大??? 答案是會的,這主要跟字節(jié)對齊有關(guān)。 比如這樣的結(jié)構(gòu)
    的頭像 發(fā)表于 11-25 16:24 ?237次閱讀

    PCM1865-Q1在LRCK低電平時只有DOUT2有數(shù)據(jù),DOUT沒有數(shù)據(jù),為什么?

    4.GPIO3 作為DOUT2接口 5.四個ADC通道,均采用單端輸入方式, 現(xiàn)遇到問題如下: 如圖:WS是LRCK,SCLK是BCK ,SDATA是DOUT , D14是DOUT2 具體問題是 在LRCK低電平時只有DOUT2有數(shù)據(jù),DOUT沒
    發(fā)表于 10-29 06:25

    TLV320aic3101的TDM設(shè)置,想用TDM采集所有數(shù)據(jù),請問怎樣設(shè)置?

    請教TLV320aic3101的TDM設(shè)置,現(xiàn)在我接了兩路聲音,一共4聲道到一片TLV320aic3101,想用TDM采集所有數(shù)據(jù),請問怎樣設(shè)置?現(xiàn)在我已經(jīng)打開了256-clock,發(fā)現(xiàn)只有其中
    發(fā)表于 10-24 07:34

    你是否真的了解結(jié)構(gòu)占用了多少字節(jié)?

    結(jié)構(gòu)成員所占內(nèi)存空間大小一般情況下,如果想知道結(jié)構(gòu)成員的內(nèi)存占用情況需要:1、先用結(jié)構(gòu)在內(nèi)
    的頭像 發(fā)表于 06-04 08:04 ?536次閱讀
    你是否真的了解<b class='flag-5'>結(jié)構(gòu)</b><b class='flag-5'>體</b>占用了多少字節(jié)?

    全國首批數(shù)據(jù)跨境場景化一般數(shù)據(jù)清單發(fā)布

    智能網(wǎng)聯(lián)汽車行業(yè)中包括四大場景共23類數(shù)據(jù)類型及158項數(shù)據(jù)字段,具體包括跨國生產(chǎn)制造、全球研發(fā)測試、售后服務(wù)以及二手車全球貿(mào)易。
    的頭像 發(fā)表于 05-20 15:24 ?371次閱讀

    嵌入式中C語言結(jié)構(gòu)基本實現(xiàn)

    C語言中的數(shù)組只能允許程序員定義存儲相同類型數(shù)據(jù)。但是結(jié)構(gòu)是C語言編程中允許您存儲不同數(shù)據(jù)類型的數(shù)據(jù)。 結(jié)構(gòu)
    的頭像 發(fā)表于 05-11 08:49 ?1097次閱讀
    嵌入式中C語言<b class='flag-5'>結(jié)構(gòu)</b><b class='flag-5'>體</b>基本實現(xiàn)

    用FreeRTOS使用隊列怎么發(fā)送一個結(jié)構(gòu)呢?

    在函數(shù)osMessageGet 只能返回一個4個字節(jié)啊。在xQueueReceive它只傳了一個uint32_tv啊,只有四個字節(jié)。 那就限制了最大的數(shù)據(jù)就是四個字節(jié)了,感覺應(yīng)該不會是這樣啊,那么我
    發(fā)表于 04-17 07:35

    揭秘USB報文的結(jié)構(gòu)與運作機制

    握手包在一個字節(jié)的數(shù)據(jù)字段后由EOP定界如果一個數(shù)據(jù)包在解碼為握手包的情況下,在一個字節(jié)后沒有以EOP結(jié)束,它必須被視為無效并被接收器忽略
    發(fā)表于 04-10 10:56 ?2221次閱讀
    揭秘USB報文的<b class='flag-5'>結(jié)構(gòu)</b>與運作機制

    C語言結(jié)構(gòu)史上最詳細(xì)的講解【軟件干貨】

    struct結(jié)構(gòu)數(shù)據(jù)類型 前言 我們知道,在C語言中有一些基本的數(shù)據(jù)類型,如?char?int?float?long?double?string(c99) 等等
    的頭像 發(fā)表于 03-28 17:52 ?810次閱讀

    磁柵尺中間沒有數(shù)據(jù)的原因及解決方法

    磁柵尺中間沒有數(shù)據(jù)的原因及解決方法!磁柵尺是一類主要用于測量長度和位置的精密測量專用工具。但是,很多時候可能會遇到磁柵尺中間沒有數(shù)據(jù)的現(xiàn)象,這可能會導(dǎo)致測量結(jié)果不準(zhǔn)確。當(dāng)我們遇到磁柵尺中間沒有數(shù)據(jù)
    的頭像 發(fā)表于 03-06 14:37 ?1021次閱讀
    磁柵尺中間沒<b class='flag-5'>有數(shù)據(jù)</b>的原因及解決方法

    arcgis值類型與字段類型不兼容

    ArcGIS是一個地理信息系統(tǒng)軟件,可以用來處理、分析和可視化地理數(shù)據(jù)。在ArcGIS中,值類型和字段類型之間需要相互匹配,否則會導(dǎo)致不兼容的錯誤。 在ArcGIS中,值類型是指存儲在數(shù)據(jù)字段
    的頭像 發(fā)表于 02-25 11:14 ?1790次閱讀

    can總線的數(shù)據(jù)幀中數(shù)據(jù)長度碼和數(shù)據(jù)字節(jié)數(shù)的關(guān)系?

    can總線的數(shù)據(jù)幀中數(shù)據(jù)長度碼和數(shù)據(jù)字節(jié)數(shù)的關(guān)系? CAN總線是一種常用于數(shù)據(jù)通信的協(xié)議,它使用數(shù)據(jù)幀來傳輸信息。在CAN
    的頭像 發(fā)表于 01-31 11:31 ?2517次閱讀