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