一粱坤、結(jié)構(gòu)體
(1)類型聲明
注意隶糕,這一步操作只是聲明了一個(gè)類型struct student瓷产,不占據(jù)棧空間或堆空間枚驻。
只有當(dāng)使用struct student這個(gè)類型濒旦,定義變量的時(shí)候,才會(huì)占據(jù)空間再登。且聲明的最后一定要加上分號(hào)尔邓。接下來進(jìn)行結(jié)構(gòu)體變量定義和賦值。
結(jié)構(gòu)體數(shù)組(數(shù)組每個(gè)元素都為struct student類型的結(jié)構(gòu)體)
結(jié)構(gòu)體數(shù)組賦值與輸出
結(jié)構(gòu)體變量的大酗笔浮:
這時(shí)候我們?nèi)绻胫肋@個(gè)結(jié)構(gòu)體的大小梯嗽,不能直接按照他的成員類型一個(gè)一個(gè)加起來那樣計(jì)算,這樣計(jì)算往往都會(huì)出錯(cuò)沽损。
這就涉及到了地址對(duì)齊的概念灯节,為了能夠減少取數(shù)據(jù)的次數(shù),計(jì)算機(jī)采用了空間換時(shí)間的方法绵估,就是地址對(duì)齊炎疆,讓不足四字節(jié)的數(shù)據(jù)(如char、short)国裳,補(bǔ)齊成四字節(jié)大小形入,方便數(shù)據(jù)取入到寄存器,避免了后續(xù)數(shù)據(jù)沒有對(duì)齊而導(dǎo)致本能一次取出的數(shù)據(jù)分為多次才可取出的情況躏救,提高數(shù)據(jù)存取效率唯笙。
上圖中的結(jié)構(gòu)體,如果我們自己算大小的話盒使,其實(shí)是4+20+1+4+4+30=63字節(jié)崩掘,但是經(jīng)打印發(fā)現(xiàn)其實(shí)是68字節(jié)。如圖
其實(shí)就是對(duì)結(jié)構(gòu)體中的char sex補(bǔ)齊了三字節(jié)少办,對(duì)char addr[30]末尾補(bǔ)齊了2字節(jié)苞慢,所以最終大小為68字節(jié)。
根據(jù)這個(gè)地址對(duì)齊的原理英妓,我們以后聲明結(jié)構(gòu)體時(shí)挽放,可以采用定義結(jié)構(gòu)體把小字節(jié)定義在一起,放到結(jié)構(gòu)體最后的方式蔓纠,這樣可以更緊湊的利用空間辑畦,避免過多的地址對(duì)齊。
(2)結(jié)構(gòu)體指針
指針訪問結(jié)構(gòu)體成員的兩種方法
結(jié)構(gòu)體指針的偏移腿倚、自增操作
這個(gè)自增操作可分為兩步:num = p->id; (p->id)++;故如果對(duì)num和p->id進(jìn)行打印纯出,應(yīng)該分別是1001和1002,打印驗(yàn)證一下。
這里僅僅是該結(jié)構(gòu)體成員id的一個(gè)自增操作暂筝。
再看下面的例子箩言,
依舊分為兩步:num = p->id; p++;?
這回便是指針變量p的自增操作了,即指針將進(jìn)行偏移焕襟,偏移的步長(zhǎng)是多少呢陨收?答案是步長(zhǎng)為該結(jié)構(gòu)體的大小。如圖
p+1相對(duì)于p偏移了68字節(jié)鸵赖,正好是一個(gè)結(jié)構(gòu)體的大小务漩。
故應(yīng)當(dāng)是從arr[0]的位置,偏移到了arr[1]的位置卫漫,即num的輸出應(yīng)為1001菲饼,而p->id為1003肾砂。打印驗(yàn)證列赎。
(3)typedef的使用(給結(jié)構(gòu)體起別名)
從前面的小例子中,可以看到我們定義的結(jié)構(gòu)體struct student類型镐确。每次定義結(jié)構(gòu)體變量的時(shí)候包吝,都需要寫上struct student類型名,而這么長(zhǎng)的類型名對(duì)我們的使用也是非常的不方便源葫,所以就輪到typedef出場(chǎng)了诗越。如圖
上圖中的用法是連續(xù)起了兩個(gè)別名,stu是結(jié)構(gòu)體類型名息堂,而pstu是結(jié)構(gòu)體指針類型名嚷狞。
這樣,以后再此定義該結(jié)構(gòu)體變量荣堰,就不需要用struct student類型來定義結(jié)構(gòu)體變量了床未,而是只用stu定義結(jié)構(gòu)體變量即可
而pstu等價(jià)于struct student1*,以后要定義結(jié)構(gòu)體指針時(shí)振坚,可直接用pstu類型名來定義薇搁。如pstu p;(p即為結(jié)構(gòu)體指針),如下圖渡八。
注意不要與下面的用法混淆?醒蟆!屎鳍!
沒加typedef的時(shí)候宏娄,這個(gè)s是結(jié)構(gòu)體變量,可直接使用逮壁,用來訪問結(jié)構(gòu)體成員孵坚。
前面加了typedef時(shí),這個(gè)s是代替了struct teacher的結(jié)構(gòu)體類型,是用來定義結(jié)構(gòu)體變量的十饥,一定要注意區(qū)分窟勃。
(4)typedef和define
define是在預(yù)處理階段起作用。故使用時(shí)前面要加#號(hào)逗堵,注意后面不加分號(hào)
typedef是在真正編譯的時(shí)候起作用秉氧,生成一個(gè)新的類型名,使用時(shí)注意前面沒#號(hào)蜒秤,后面有分號(hào)汁咏。
兩種用法效果相同,都是使用INTEGER代替了int作媚。
這里的INTEGER顯示橙色高亮是因?yàn)樯蠄D使用typedef和define時(shí)攘滩,#define在下面,由于遵守就近原則纸泡,所以下面這個(gè)INTEGER其實(shí)由#define進(jìn)行的別名替代漂问。故typedef和#define不要一起使用,使用一個(gè)即可女揭。
基本了解了結(jié)構(gòu)體的使用方法后蚤假,就可以搭配指針,適當(dāng)進(jìn)行一些數(shù)據(jù)結(jié)構(gòu)的編寫了吧兔,如鏈表磷仰、樹等。
二境蔼、共用體
共用體灶平,顧名思義,即是共用體內(nèi)各個(gè)成員共同使用該空間箍土。
(1)不同于結(jié)構(gòu)體的方面
接下來羅列出共用體和結(jié)構(gòu)體不同的地方:
?1.共用體一般用于滿足某個(gè)接口逢享,可能會(huì)接收不同類型的參數(shù)的需求。
?2.共用體的大小就是該共用體中最大的成員的大小涮帘。
?3.同一段內(nèi)存可以用來存放幾種不同類型的成員拼苍,但在每個(gè)瞬間只能存放其中一種,而不能同時(shí)存放幾種调缨。
?4.共用體變量中起作用的成員是最后一次存入的成員疮鲫,存入一個(gè)新成員后,原來起作用的成員就失去了作用弦叶。
?5.共用體變量的地址和他的各成員的地址都是同一地址俊犯。如果共用體變量a的起始地址為1000,那么共用體內(nèi)成員i,ch,f的起始地址均為1000.
?6.不能對(duì)共用體變量名賦值伤哺,也不能企圖引用共用體變量名來得到一個(gè)值燕侠。
(2)共用體類型和共用體變量的定義
共用體類型的定義和共用體變量的定義操作都是一致的者祖。
對(duì)于其成員的賦值也和結(jié)構(gòu)體一直,如圖
不過要注意绢彤,與結(jié)構(gòu)體不同的是七问,結(jié)構(gòu)體如此賦值后,每個(gè)成員都被賦了值茫舶,而共用體因?yàn)槭浅蓡T共用這一段空間械巡,并不是共存的關(guān)系,所以此時(shí)共用體中起作用的成員只有d.f饶氏,即只有d.f被成功賦值了讥耗。
進(jìn)行斷點(diǎn)分析打印展示。
可以看到疹启,每當(dāng)一個(gè)成員被賦值的時(shí)候古程,其他的成員便失效了。
(3)共用體大小
只與共用體中最大的成員有關(guān)喊崖,大小與其中最大的成員相等挣磨,即如上面定義的共用體,大小就是4字節(jié)贷祈。
如果對(duì)成員進(jìn)行更改趋急,將int改為long,則大小變?yōu)?字節(jié)势誊。
最后說一句,共用體類型可以出現(xiàn)在結(jié)構(gòu)體類型定義中谣蠢,也可以定義共用體數(shù)組粟耻;結(jié)構(gòu)體可以出現(xiàn)在共用體類型定義中,數(shù)組也可以作為共用體的成員眉踱。這點(diǎn)共用體和結(jié)構(gòu)體完全一致挤忙。
三、枚舉
假如我們想要星期日到星期六表示數(shù)字0~6(即星期日==0谈喳,星期一==1...類推)册烈,以此便捷地表示星期幾。
如果使用#define的話婿禽,需要寫七句代碼分別定義赏僧。這時(shí)候我們就可以使用枚舉了。
枚舉就是將變量的值一一列舉出來扭倾,變量的值只限于在所列舉的值的范圍內(nèi)淀零。
(1)聲明枚舉類型
枚舉元素作為常量是有值的,C語言編譯時(shí)膛壹,按定義的順序使他們的值為0驾中,1唉堪,2........如圖
如果在聲明時(shí),令sun=5肩民,則后面的元素都跟著依次累加唠亚。
要注意,C語言在編譯時(shí)對(duì)枚舉元素是按常量處理的持痰,故稱枚舉常量趾撵,因?yàn)樗麄儾皇亲兞浚圆荒軐?duì)其賦值共啃。
(2)定義枚舉變量
枚舉值可以用來做判斷和比較占调。