C語(yǔ)言編程基礎(chǔ)學(xué)習(xí)中的結(jié)構(gòu)體數(shù)據(jù)對(duì)齊

C語(yǔ)言是面向過程的,而C++是面向?qū)ο蟮?/b>

C和C++的區(qū)別:

C是一個(gè)結(jié)構(gòu)化語(yǔ)言翘鸭,它的重點(diǎn)在于算法和數(shù)據(jù)結(jié)構(gòu)滴铅。C程序的設(shè)計(jì)首要考慮的是如何通過一個(gè)過程,對(duì)輸入(或環(huán)境條件)進(jìn)行運(yùn)算處理得到輸出(或?qū)崿F(xiàn)過程(事務(wù))控制)就乓。

C++汉匙,首要考慮的是如何構(gòu)造一個(gè)對(duì)象模型,讓這個(gè)模型能夠契合與之對(duì)應(yīng)的問題域生蚁,這樣就可以通過獲取對(duì)象的狀態(tài)信息得到輸出或?qū)崿F(xiàn)過程(事務(wù))控制噩翠。 所以C與C++的最大區(qū)別在于它們的用于解決問題的思想方法不一樣。之所以說C++比C更先進(jìn)邦投,是因?yàn)椤?設(shè)計(jì)這個(gè)概念已經(jīng)被融入到C++之中 ”伤锚。

C與C++的最大區(qū)別:在于它們的用于解決問題的思想方法不一樣。之所以說C++比C更先進(jìn)志衣,是因?yàn)椤?設(shè)計(jì)這個(gè)概念已經(jīng)被融入到C++之中 ”屯援,而就語(yǔ)言本身而言,在C中更多的是算法的概念念脯。那么是不是C就不重要了玄呛,錯(cuò)!算法是程序設(shè)計(jì)的基礎(chǔ)和二,好的設(shè)計(jì)如果沒有好的算法,一樣不行耳胎。而且惯吕,“C加上好的設(shè)計(jì)”也能寫出非常好的東西。

之前使用結(jié)構(gòu)體不是很多怕午,了解不多废登,最近使用結(jié)構(gòu)體遇到數(shù)據(jù)對(duì)齊問題,于是決定把這個(gè)結(jié)構(gòu)體的數(shù)據(jù)對(duì)齊問題摸透郁惜,隨便收錄入我的博客堡距。

作為一種數(shù)據(jù)集合甲锡,struct常用在數(shù)據(jù)結(jié)構(gòu)中。而struct的字節(jié)對(duì)齊方式對(duì)于嵌入式底層的程序員來(lái)講是必須掌握的羽戒。

現(xiàn)代計(jì)算機(jī)中內(nèi)存空間都是按照byte劃分的缤沦,從理論上講似乎對(duì)任何類型的變量的訪問可以從任何地址開始,但實(shí)際情況是在訪問特定類型變量的時(shí)候經(jīng)常在特定的內(nèi)存地址訪問易稠,這就需要各種類型數(shù)據(jù)按照一定的規(guī)則在空間上排列缸废,而不是順序的一個(gè)接一個(gè)的排放,這就是對(duì)齊驶社。對(duì)齊的作用和原因:各個(gè)硬件平臺(tái)對(duì)存儲(chǔ)空間的處理上有很大的不同企量。一些平臺(tái)對(duì)某些特定類型的數(shù)據(jù)只能從某些特定地址開始存取。比如有些架構(gòu)的CPU在訪問 一個(gè)沒有進(jìn)行對(duì)齊的變量的時(shí)候會(huì)發(fā)生錯(cuò)誤,那么在這種架構(gòu)下編程必須保證字節(jié)對(duì)齊.其他平臺(tái)可能沒有這種情況亡电,但是最常見的是如果不按照適合其平臺(tái)要求對(duì) 數(shù)據(jù)存放進(jìn)行對(duì)齊届巩,會(huì)在存取效率上帶來(lái)?yè)p失。比如有些平臺(tái)每次讀都是從偶地址開始份乒,如果一個(gè)int型(假設(shè)為32位系統(tǒng))如果存放在偶地址開始的地方恕汇,那么一個(gè)讀周期就可以讀出這32bit,而如果存放在奇地址開始的地方冒嫡,就需要2個(gè)讀周期拇勃,并對(duì)兩次讀出的結(jié)果的高低字節(jié)進(jìn)行拼湊才能得到該32bit數(shù) 據(jù)。顯然在讀取效率上下降很多孝凌。

首先我們?cè)赩C++6.0寫個(gè)小程序測(cè)試下方咆,

小編推薦一個(gè)學(xué)C語(yǔ)言/C++的學(xué)習(xí)裙【 六九九,四七零蟀架,五九六 】瓣赂,無(wú)論你是大牛還是小白,是想轉(zhuǎn)行還是想入行都可以來(lái)了解一起進(jìn)步一起學(xué)習(xí)片拍!裙內(nèi)有開發(fā)工具煌集,很多干貨和技術(shù)資料分享!

程序運(yùn)行后的結(jié)果:

Sizeof(A)=8

Sizeof(B)=12

Press any key to continue

結(jié)構(gòu)體A中包含了4字節(jié)長(zhǎng)度的int一個(gè)捌省,1字節(jié)長(zhǎng)度的char一個(gè)和2字節(jié)長(zhǎng)度的short型數(shù)據(jù)一個(gè),B也一樣;按理說A,B大小應(yīng)該都是7字節(jié)苫纤。之所以出現(xiàn)上面的結(jié)果是因?yàn)榫幾g器要對(duì)數(shù)據(jù)成員在空間上進(jìn)行對(duì)齊。以上是按默認(rèn)方式對(duì)齊纲缓。

默認(rèn)對(duì)齊:各成員變量在存放的時(shí)候根據(jù)在結(jié)構(gòu)中出現(xiàn)的順序依次申請(qǐng)空間卷拘,同時(shí)按照上面的對(duì)齊方式調(diào)整位置,空缺的字節(jié)VC會(huì)自動(dòng)填充祝高。同時(shí)VC為了確保結(jié)構(gòu)的大小為結(jié)構(gòu)的字節(jié)邊界數(shù)(即該結(jié)構(gòu)中占用最大空間的類型所占用的字節(jié)數(shù))的倍數(shù)栗弟,所以在為最后一個(gè)成員變量申請(qǐng)空間后,還會(huì)根據(jù)需要自動(dòng)填充空缺的字節(jié)

默認(rèn)對(duì)齊方式的過程:

結(jié)構(gòu)A分配空間的時(shí)候工闺,先為第一個(gè)成員a分配空間乍赫,其起始地址跟結(jié)構(gòu)的起始地址相同(剛好偏移量0剛好為sizeof(int)的倍數(shù))瓣蛀,該成員變量占用sizeof(int)=4個(gè)字節(jié);接下來(lái)為第二個(gè)成員b分配空間雷厂,這時(shí)下一個(gè)可以分配的地址對(duì)于結(jié)構(gòu)的起始地址的偏移量為4惋增,是sizeof(char)的倍數(shù),所以把成員b存放在偏移量為4的地方滿足對(duì)齊方式罗侯,該成員變量占用sizeof(char)=1個(gè)字節(jié)器腋;接下來(lái)為第三個(gè)成員c分配空間,這時(shí)下一個(gè)可以分配的地址對(duì)于結(jié)構(gòu)的起始地址的偏移量為5钩杰,不是sizeof(short)=2的倍數(shù)纫塌,為了滿足對(duì)齊方式對(duì)偏移量的約束問題,VC自動(dòng)填充1個(gè)字節(jié)(這一個(gè)字節(jié)沒有放什么東西)讲弄,這時(shí)下一個(gè)可以分配的地址對(duì)于結(jié)構(gòu)的起始地址的偏移量為6措左,剛好是sizeof(short)=2的倍數(shù),所以把c存放在偏移量為6的地方避除,該成員變量占用sizeof(short)=2個(gè)字節(jié)怎披;這時(shí)整個(gè)結(jié)構(gòu)的成員變量已經(jīng)都分配了空間,總的占用的空間大小為:4+1+1+2=8瓶摆,剛好為結(jié)構(gòu)的字節(jié)邊界數(shù)(即結(jié)構(gòu)中占用最大空間的類型所占用的字節(jié)數(shù)sizeof(int)=4)的倍數(shù)凉逛,所以沒有空缺的字節(jié)需要填充。所以整個(gè)結(jié)構(gòu)的大小為:sizeof(A)=4+1+1+2=8群井,其中有1個(gè)字節(jié)是VC自動(dòng)填充的状飞,沒有放任何有意義的東西。

結(jié)構(gòu)B分配空間的時(shí)候书斜,先為第一個(gè)成員a分配空間诬辈,其起始地址跟結(jié)構(gòu)的起始地址相同(剛好偏移量0剛好為sizeof(char)的倍數(shù)),該成員變量占用sizeof(char)=1個(gè)字節(jié)荐吉;接下來(lái)為第二個(gè)成員b分配空間焙糟,這時(shí)下一個(gè)可以分配的地址對(duì)于結(jié)構(gòu)的起始地址的偏移量為1,不是sizeof(int)的倍數(shù)样屠,為了滿足對(duì)齊方式對(duì)偏移量的約束問題穿撮,VC自動(dòng)填充3個(gè)字節(jié)(這三個(gè)字節(jié)沒有放什么東西),這時(shí)下一個(gè)可以分配的地址對(duì)于結(jié)構(gòu)的起始地址的偏移量為4,剛好是sizeof(int)=4的倍數(shù)痪欲。所以把成員b存放在偏移量為4的地方滿足對(duì)齊方式悦穿,該成員變量占用sizeof(int)=4個(gè)字節(jié);接下來(lái)為第三個(gè)成員c分配空間勤揩,這時(shí)下一個(gè)可以分配的地址對(duì)于結(jié)構(gòu)的起始地址的偏移量為8,剛好是sizeof(short)=2的倍數(shù)秘蛔,所以把c存放在偏移量為8的地方陨亡,該成員變量占用sizeof(short)=2個(gè)字節(jié)傍衡;這時(shí)整個(gè)結(jié)構(gòu)的成員變量已經(jīng)都分配了空間,總的占用的空間大小為:1+3+4+2=10负蠕,不是結(jié)構(gòu)的字節(jié)邊界數(shù)(即結(jié)構(gòu)中占用最大空間的類型所占用的字節(jié)數(shù)sizeof(int)=4)的倍數(shù)蛙埂,所以要填補(bǔ)2個(gè)空缺的字節(jié)。所以整個(gè)結(jié)構(gòu)的大小為:sizeof(B)=1+3+4+2+2=12遮糖,其中有5個(gè)字節(jié)是VC自動(dòng)填充的绣的,沒有放任何有意義的東西。

VC中提供了#pragmapack(n)來(lái)設(shè)定變量以n字節(jié)對(duì)齊方式欲账。n字節(jié)對(duì)齊就是說變量存放的起始地址的偏移量有兩種情況:第一屡江、如果n大于等于該變量所占用的字節(jié)數(shù),那么偏移量必須滿足默認(rèn)的對(duì)齊方式赛不,第二惩嘉、如果n小于該變量的類型所占用的字節(jié)數(shù),那么偏移量為n的倍數(shù)踢故,不用滿足默認(rèn)的對(duì)齊方式文黎。結(jié)構(gòu)的總大小也有個(gè)約束條件,分下面兩種情況:如果n大于所有成員變量類型所占用的字節(jié)數(shù)殿较,那么結(jié)構(gòu)的總大小必須為占用空間最大的變量占用的空間數(shù)的倍數(shù)耸峭;

否則必須為n的倍數(shù)。下面舉例說明其用法淋纲。

#pragmapack(push) //保存對(duì)齊狀態(tài)

#pragmapack(4)//設(shè)定為4字節(jié)對(duì)齊

小編推薦一個(gè)學(xué)C語(yǔ)言/C++的學(xué)習(xí)裙【 六九九劳闹,四七零,五九六 】帚戳,無(wú)論你是大牛還是小白玷或,是想轉(zhuǎn)行還是想入行都可以來(lái)了解一起進(jìn)步一起學(xué)習(xí)!裙內(nèi)有開發(fā)工具片任,很多干貨和技術(shù)資料分享偏友!

#pragmapack(pop)//恢復(fù)對(duì)齊狀態(tài)以上結(jié)構(gòu)的大小為16,下面分析其存儲(chǔ)情況对供,首先為m1分配空間位他,其偏移量為0,滿足我們自己設(shè)定的對(duì)齊方式(4字節(jié)對(duì)齊)产场,m1占用1個(gè)字節(jié)鹅髓。接著開始為m4分配空間,這時(shí)其偏移量為1京景,需要補(bǔ)足3個(gè)字節(jié)窿冯,這樣使偏移量滿足為n=4的倍數(shù)(因?yàn)閟izeof(double)大于n),m4占用8個(gè)字節(jié)。接著為m3分配空間确徙,這時(shí)其偏移量為12醒串,滿足為4的倍數(shù)执桌,m3占用4個(gè)字節(jié)。這時(shí)已經(jīng)為所有成員變量分配了空間芜赌,共分配了16個(gè)字節(jié)仰挣,滿足為n的倍數(shù)。如果把上面的#pragmapack(4)改為#pragma pack(8)缠沈,那么我們可以得到結(jié)構(gòu)的大小為24

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末膘壶,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子洲愤,更是在濱河造成了極大的恐慌颓芭,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件禽篱,死亡現(xiàn)場(chǎng)離奇詭異畜伐,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)躺率,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門玛界,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人悼吱,你說我怎么就攤上這事慎框。” “怎么了后添?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵笨枯,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我遇西,道長(zhǎng)馅精,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任粱檀,我火速辦了婚禮洲敢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘茄蚯。我一直安慰自己压彭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布渗常。 她就那樣靜靜地躺著壮不,像睡著了一般。 火紅的嫁衣襯著肌膚如雪皱碘。 梳的紋絲不亂的頭發(fā)上询一,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼健蕊。 笑死缓醋,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绊诲。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼褪贵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼掂之!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起脆丁,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤世舰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后槽卫,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體跟压,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年歼培,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了震蒋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡躲庄,死狀恐怖查剖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情噪窘,我是刑警寧澤笋庄,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站倔监,受9級(jí)特大地震影響直砂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜浩习,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一静暂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瘦锹,春花似錦籍嘹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至听绳,卻和暖如春颂碘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工头岔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留塔拳,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓峡竣,卻偏偏與公主長(zhǎng)得像靠抑,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子适掰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容