?1、結構體聲明
網站的建設創新互聯公司專注網站定制,經驗豐富,不做模板,主營網站定制開發.小程序定制開發,H5頁面制作!給你煥然一新的設計體驗!已為生料攪拌車等企業提供專業服務。?2、結構體自引用
?3、結構體變量的定義和初始化
?4、結構體內存對齊
?5、結構體傳參
二、位段?1、什么是位段
?2、位段內存的分配問題
?3、位段跨平臺問題
一、結構體?在開發的過程中,我們難免要去描述一些復雜的對象,而想要描述這些對象,就不能使用之前學過的int,double
等這些類型。這時候就可以用到結構體了,結構體是一些值的集合,這些值稱為成員變量。結構的每個成員可以是不同類型的變量。
?1、結構體聲明
下面是聲明一個學生類型,例如:
struct Stu
{
char name[20];//名字
int age;//年齡
char sex[5];//性別
char id[20];//學號
};
?還有一種是結構體的特殊聲明,就是可以不完全的聲明。表示匿名結構體,即沒有寫結構體標簽。就如下面這種形式:
//匿名結構體類型
struct
{
int a;
char b;
float c;
}x;
struct
{
int a;
char b;
float c;
}a[20],*p;
?上述定義的兩個結構體類型都是struct,沒有對應的結構體標簽,所以是匿名得結構體。?而匿名結構體因為沒有結構體標簽,每個struct 匿名結構體類型都是獨立的,聲明匿名結構體類型后,因為匿名結構體類型都是獨立的。它只能在聲明定義的時候在后面同時創建對應的結構體變量。
?2、結構體自引用
?結構體里面可以放相同或者不同類型的多個成員變量,那么結構體里面的成員變量可以是當前結構體類型創建的成員變量嗎?答:是可以的。
?首先先看一看上面的代碼是否可以,答:這種寫法是錯誤的,因為這個結構體類型里面的成員變量還沒描述完就直接使用自身結構體類型創建個變量,這樣是行不通的。
正確的結構體自引用方法是:
struct Node
{
int data;
struct Node* next;
};
這樣寫就能夠明確結構體指針類型字節大小的,并且還能用這個結構體類型創建其他變量,例如創建一個s的變量,里面的結構體指針成員變量可以存放&s ,這個時候就可以存放這個結構體類型創建的另外的變量的地址,可以通過解引用訪問到其他結構體變量。
?3、結構體變量的定義和初始化
有了上面的結構體類型,那如何定義變量,其實很簡單。
?定義完變量就該初始化變量,如下:
//初始化:定義變量的同時賦初值
struct Book p3 = { x , y };
struct Book //類型聲明
{
char BookName[20];//書名
char author[20];//作者
};
struct Book s = {"C語言程序設計","zhangsan" };//初始化
?用struct Node類型創建了變量n1 和n2, 對n1和n2結構體變量嵌套進行初始化,對n1變量進行初始化時,當初始化到p這個struct Book變量時,因為其自身也是一個結構體變量,對結構體變量初始化里面成員可能有多個需要再嵌套一個{ },此時應該對該結構體變量里面的成員變量先進行初始化,最后在為最后一個結構體指針變量進行初始化為NULL,這就是結構體嵌套初始化。
?4、結構體內存對齊
?在前面我們已經掌握結構體的使用,但是我們還不清楚結構體大小的計算,想要計算結構體的大小,首先我們先要明白結構體內存的對齊,才能夠準確的計算結構體的大小。
?重點:計算結構體大小,首先我掌握結構體的對齊規則:
?(1)第一個成員在與結構體變量偏移量為0的地址處。
?(2)其他成員變量要對齊到某個數字(對齊數)的整數倍的地址處。
?對齊數 = 編輯器默認的一個對齊數與該成員大小的較小值。VS中默認對齊數為8。
?(3)結構體總大小為大對齊數(每個成員變量都有一個對齊數)的整數倍。
?(4)如果嵌套了結構體的情況,嵌套的結構體對齊到自己的大對齊數的整數倍處,結構體的整體大小就是所有大對齊數(含嵌套結構體的對齊數)的整數倍。
?c1為結構體S1的第一個成員變量,所以對齊到偏移量0處,c1成員對齊數為1,并且占用1個字節,所以偏移量0開始的第一個內存單元就為c1的空間。
?整形 i 為結構體的第二個成員變量,對齊到自身成員對齊數最小整數倍位置,偏移量為0處的內存單元已經存放了c1,所以需要往后到偏移量為4的位置,才是i成員對齊數4的倍數,即從偏移處4開始往后存放4個字節。
??c2為結構體的第三個成員變量,對齊數為1個字節,當前可用的偏移量從8開始,而8是對齊數1的倍數,此時從偏移量為8的位置開始存放c2,c2占用一個字節,所以偏移8處就位c2存放的地址。此時,所有的成員變量都分配好空間,是從偏移量0到8,占用了9個字節,而結構體總大小為所有成員變量大對齊數4的倍數,9不是4的倍數,所以需要浪費3個字節,最終計算出的大小為12。
?結構體S2的計算方法和S1相似,根據上圖可以容易的計算出,在此處我就略寫了。?
?為什么存在內存對齊???(有兩個原因)
?(1)平臺原因(移植原因):不是所有的硬件平臺都能訪問任意地址上的任意數據的;某些硬件平臺只能在某些地址處取某些特 定類型的數據,否則拋出硬件異常。
?(2)性能原因:數據結構(尤其是棧)應該盡可能地在自然邊界上對齊。原因在于,為了訪問未對齊的內存,處理器需要作兩次內存訪問;而對齊的內存訪問僅需要一次訪問。
? 總體來說,結構體的內存對齊是拿空間來換取時間的做法。所以我們在設計結構體的時候,盡可能的讓占用空間小的成員集中在一起。
??5、結構體傳參
struct S
{
int data[1000];
int num;
};
struct S s = { {1,2,3,4}, 1000 };
//結構體傳參
void print1(struct S s)
{
printf("%d\n", s.num);
}
//結構體地址傳參
void print2(struct S* ps)
{
printf("%d\n", ps->num);
}
int main()
{
print1(s); //傳結構體
print2(&s); //傳地址
return 0;
}
?上述運用了兩種傳送形式,一種是直接傳結構體,另一種是傳地址。這兩種方法我們選第二種傳地址的方法,因為函數傳參的時候,參數是需要壓棧,會有時間和空間上的系統開銷。 如果傳遞一個結構體對象的時候,結構體過大,參數壓棧的的系統開銷比較大,所以會導致性能的下降。
二、位段?1、什么是位段
?位段的聲明和結構是類似的,有兩個不同:
1.位段的成員必須是 int、unsigned int 或signed int 。
2.位段的成員名后邊有一個冒號和一個數字。
上述A就是一個位段類型。此時計算結構體A的大小為8個字節。
因為一個int類型是4個字節 = 32個bit,所以我們先開辟一個int類型的4個字節32存放它們,a 占2個bit,b占5個bit,c占10個bit,此時,已經占用了17個bit,而d需要30個bit,這時放不下d,所以還需要再開辟一個int類型的4個字節存放d,所以結構體A的大小為8個字節。
?2、位段內存的分配問題
1. 位段的成員可以是 int unsigned? int signed? int 或者是 char (屬于整形家族)類型
2. 位段的空間上是按照需要以4個字節( int )或者1個字節( char )的方式來開辟的。
3. 位段涉及很多不確定因素,位段是不跨平臺的,注重可移植的程序應該避免使用位段。
?接下來我們通過例子能夠更好地講解位段內存的分配,并且還能清晰看出數據是怎么存放的。
下面我通過簡單的畫圖可以幫助大家更好地理解。?
???????
?3、位段跨平臺問題
1. int 位段被當成有符號數還是無符號數是不確定的。
2. 位段中大位的數目不能確定。(16位機器大16,32位機器大32,寫成27,在16位機 器會出問題。
3. 位段中的成員在內存中從左向右分配,還是從右向左分配標準尚未定義。
4. 當一個結構包含兩個位段,第二個位段成員比較大,無法容納于第一個位段剩余的位時,是 舍棄剩余的位還是利用,這是不確定的。
?總結:跟結構體相比,位段可以達到同樣的效果,但是可以很好的節省空間,但是有跨平臺的問題存在。
本文要是有不足的地方,歡迎大家在下面評論,我會在第一時間更正。
???????
老鐵們,記著點贊加關注哦!!!你是否還在尋找穩定的海外服務器提供商?創新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統配攻擊溯源,準確流量調度確保服務器高可用性,企業級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧
網站題目:【C語言】自定義類型(結構體,位段)詳解-創新互聯
轉載來源:http://vcdvsql.cn/article14/ejgde.html
成都網站建設公司_創新互聯,為您提供品牌網站建設、建站公司、營銷型網站建設、軟件開發、App開發、品牌網站制作
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯