日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > 單片機(jī) > 程序喵大人
[導(dǎo)讀]之前我寫(xiě)過(guò)一篇《如何設(shè)計(jì)一個(gè)C的類(lèi)》,今天這里繼續(xù)聊聊如何設(shè)計(jì)結(jié)構(gòu)體,注意本文不介紹在C中結(jié)構(gòu)體和類(lèi)具體有什么區(qū)別,本文所說(shuō)的結(jié)構(gòu)體是指只有數(shù)據(jù)字段不帶任何函數(shù)的那種結(jié)構(gòu)體。當(dāng)創(chuàng)建結(jié)構(gòu)體的實(shí)例時(shí),結(jié)構(gòu)體的數(shù)據(jù)成員會(huì)按其聲明的順序連續(xù)存儲(chǔ)。然而,這個(gè)聲明的順序也是有學(xué)問(wèn)的,順序不同...

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


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


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


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



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


例如:

struct S { short int a; // 2字節(jié) // 6個(gè)空洞 double b; // 8 int d; // 4 // 4個(gè)空洞};S ArrayOfStructures[100];這里,在a和b之間有6個(gè)未使用的字節(jié),因?yàn)閎必須從一個(gè)能被8整除的地址開(kāi)始。


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


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

struct S { double b; // 8 int d; // 4 short int a; // 2 // 2個(gè)空洞};S ArrayOfStructures[100];這種重新排序使結(jié)構(gòu)體變小了8個(gè)字節(jié),那整個(gè)數(shù)組則變小了800個(gè)字節(jié)


在此特性上,類(lèi)和結(jié)構(gòu)體相同。通過(guò)重新排序數(shù)據(jù)成員,結(jié)構(gòu)體對(duì)象和類(lèi)對(duì)象通??梢宰兊酶?。如果類(lèi)至少有一個(gè)虛成員函數(shù),則在第一個(gè)數(shù)據(jù)成員之前或最后一個(gè)成員之后會(huì)有一個(gè)指向虛函數(shù)表的指針。該指針在32位系統(tǒng)中為4字節(jié),在64位系統(tǒng)中為8字節(jié)。


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


還有一個(gè)知識(shí)點(diǎn):


如果數(shù)據(jù)成員相對(duì)于結(jié)構(gòu)體或類(lèi)開(kāi)頭的偏移量小于128,則訪問(wèn)數(shù)據(jù)成員的代碼會(huì)更加緊湊,因?yàn)樵撈屏靠梢允褂?位有符號(hào)的數(shù)字來(lái)表示。如果相對(duì)于結(jié)構(gòu)體或類(lèi)的開(kāi)頭的偏移量是128字節(jié)或更多,那么偏移量必須表示為一個(gè)32位數(shù)字(指令集在8位到32位之間沒(méi)有偏移量)。例如:

struct S { int a[100]; // 400 int b; // 4 int read() { return b; }};

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


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


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

struct S { int deskA; double deskB; bool deskC; int chairA; double chairB; bool chairC;};可能這樣修改后結(jié)構(gòu)體會(huì)更小:

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


小總結(jié):

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

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

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


打完收工。


C 學(xué)習(xí)資料免費(fèi)獲取方法:關(guān)注程序喵大人,后臺(tái)回復(fù)“程序喵”即可免費(fèi)獲取40萬(wàn)字C 進(jìn)階獨(dú)家學(xué)習(xí)資料。





往期推薦


1、少寫(xiě)點(diǎn)if-else吧,它的效率有多低你知道嗎?2、年度原創(chuàng)好文匯總3、全網(wǎng)首發(fā)!!C 20新特性全在這一張圖里了4、他來(lái)了,他來(lái)了,C 17新特性精華都在這了5、一文讓你搞懂設(shè)計(jì)模式6、C 11新特性,所有知識(shí)點(diǎn)都在這了!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專(zhuān)欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉