結構基礎知識
聚合資料型別能夠同時儲存超過乙個的單獨資料。c提供了兩種型別的聚合資料型別,分別是陣列和結構體。陣列是相同元素的集合,它的每個元素是通過下標引用或指標間接訪問的。結構體也是一些值的的集合,這些值稱為它 的成員,但乙個結構的成員可能具有不同的型別。陣列元素可以通過下標訪問,這是因為陣列元素長度相同,但在結構體中並非如此,由於每個成員的型別可能不同,那麼長度也就可能不同,所以就不能通過下標來訪問。但是結構體成員都有自己的名字,他們是通過名字訪問的。另外,結構體在表示式中使用時,不能被替換為指標。結構體變數也無法使用下標來選擇特定的成員。
結構體的宣告
這個結構體建立了結構體變數x,結構體包含了2個成員:整型a,字元ch。
結構體宣告哪些可以省略?
標籤a可以省略,那麼就是匿名結構體型別,但不建議。在宣告時可以沒有結構體變數x,如果有,那麼該變數為全域性變數。如果在main函式中,就是區域性變數。
如下:
struct a x;
int x;
struct a 相當於int ,也就是型別,屬於結構體型別,x是結構體變數。
上面兩個結構都忽略了結構體標籤(如a),那麼這個語句成立嗎?p=&x?
警告:這兩個宣告被編譯器當做兩種截然不同 的型別,即使成員相同。所以,變數a,p,x,型別不同,不可p=&x。
注:用typedef後,******是個型別名,可以建立變數。
訪問結構體成員
通過.操作符訪問成員:
通過->進行訪問:
兩者結果為:10 zhangsan
結構體自引用
我們已經知道在結構體中可以包含陣列,指標,標量,結構體...那麼結構體裡面能不能包含該結構體本身呢?
不可以,因為不知道結構體大小,無法開闢空間存y。
正確的結構體自引用如下:
因為struct stu *y是指標型別,即為4個位元組,可以開闢空間。
結構的不完整宣告
偶爾,必須宣告一些相互之間存在依賴的結構。即,乙個結構包含了另乙個結構的乙個或多個成員。和自引用一樣,至少乙個結構必須在另乙個結構中以指標的形式存在。問題在於宣告部分:如果每個結構體都引用了其他 結構的標籤,哪個結構應該首先宣告?
這個問題的解決方案是使用不完整宣告,它宣告乙個作為結構標籤的識別符號。然後,把這個標籤用在不需要知道這個結構的長度的宣告中,如宣告指向這個結構的指標。
結構體變數的定義和初始化
結構的初始化方式和陣列初始化很相似。乙個位於一對花括號內部,由逗號分隔的初始值列表可用於結構的初始化。這些值根據結構成員列表的順序寫出。
結構體內存對齊
為什麼存在記憶體對齊?
1.平台原因(移植原因)
不是所有的硬體平台都能訪問任意位址上的任意資料;某些硬體平台只能在某些位址處取某些特定型別的資料,否則就丟擲硬體異常。
2.效能原因:
資料結構(尤其是棧)應該盡能地在自然邊界上對齊。原因在於,為了訪問未對齊的記憶體,處理器需要做兩次記憶體訪問;而對齊的記憶體訪問需要訪問一次。
圖如下:
結構體對齊規則:
1.第乙個成員在與結構體變數偏移量為0的位址處。
2.其他成員變數要對齊到某個數字(對齊數)的整數倍的位址處。對齊數=編譯器預設的對齊數與該成員大小的較小值。vs中預設對齊數為8,linux預設對齊數為4.
3.結構體總大小為最大對齊數(每個成員都有乙個對齊數)的整數倍。
4.如果巢狀了結構體的情況,巢狀的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含巢狀結構體的對齊數)的整數倍。
那麼首先看一道題:
通過記憶體對齊規則,答案肯定不是6,答案是12,解釋如下:
再看其他例子:
結果為8。1+1+2+4=8,8是最大對齊數4的倍數。
結果為16。8+1+3+4=16,16是最大對齊數4的倍數。
結果為32。1+7+16+8=32,32是最大對齊數8的倍數。
結構體傳參
我們知道陣列傳參會發生降級,那麼結構體會不會降級呢?
結構體傳參有兩種形式,乙個是傳結構體,乙個是傳位址,但是建議選擇傳位址。因為在棧幀知識中,函式傳參,是需要壓入棧的,但是如果傳結構體物件時,結構體過大,所佔空間也就過大,會導致效能下降。
搬 結構體(宣告 初始化 記憶體對齊 如何傳參)
結構基礎知識 聚合資料型別能夠同時儲存超過乙個的單獨資料。c提供了兩種型別的聚合資料型別,分別是陣列和結構體。陣列是相同元素的集合,它的每個元素是通過下標引用或指標間接訪問的。結構體也是一些值的的集合,這些值稱為它 的成員,但乙個結構的成員可能具有不同的型別。陣列元素可以通過下標訪問,這是因為陣列元...
變數定義 宣告 初始化
變數定義就是告訴編譯器在何處建立變數的儲存,以及如何建立變數的儲存。變數定義指定乙個資料型別,幷包含了該型別的乙個或多個變數的列表,如下所示 type variable list 在這裡,type 必須是乙個有效的 c 資料型別,可以是 char w char int float double bo...
宣告 初始化和例項化的區別
我算是剛入門的菜鳥,今天說下宣告 初始化和例項化的區別和使用,如有不對的地方歡迎各位指正。宣告是指使用乙個物件的時候,先定義屬於哪個型別並,比如string str str是宣告 定義 了乙個string型別的物件。初始化可以理解為給宣告的物件賦值的過程。string str hello str現在...