1-C語言之結構體、共用體、列舉
一、關鍵字說明
C語言有32個關鍵字,C語言通過關鍵字的使用使編譯器進行相關的操作
結構體對應關鍵字struct
共用體(聯合體)對應的關鍵字是union
列舉型別對應的關鍵字是enum
二、結構體、共用體(聯合體)、列舉定義
結構體的定義:一種或多種基本型別或構造型別的資料的集合(構造型別)。
共用體(聯合體)的定義:所謂的共用體(聯合體)就是其中的成員共用一段記憶體,記憶體的大小由最大的那個成員的大小確定。
列舉型別:C語言等計算機程式語言中是一種構造資料型別,它用於宣告一組命名的常數,當一個變數有幾種可能的取值時,可以將它定義為列舉型別。
三、結構體、共用體與記憶體分配的關係
結構體:記憶體對齊——最大以4位元組對齊(32位機)
共用體:
四、結構體的使用
step1:結構體的定義
(1)先定義結構體型別,再去定義結構體變數
(2)struct 結構體型別名{
成員列表
};
(3)構造的資料型別是 struct 結構體型別名
(4)例子
struct stu{
int num;
char name[20];
char sex;
};
step2:結構體取成員操作
(1)採用.取結構體成員
(2)採用->取結構體成員
定義結構體指標,用結構體指標->成員變數進行取值操作
(3)基址 + 偏移 = 取成員
step3:結構體的初始化和使用
(1)直接定義時並初始化
(2)採用bzero和memset對結構體進行初始化,初始化後直接進行賦值操作
step4:結構體陣列
(1)結構體陣列的定義:結構體陣列是個陣列,由若干個相同型別的結構體變數構成的集合
(2)結構體陣列(類似int a[10])的定義方法:
.NOTE:結構體陣列從兩方面來理解
(1)結構體和基本資料型別,原則上都是資料型別,一個是構造資料型別,一個是基本資料型別
(2)陣列方面:基本資料型別int a[10], 構造資料型別struct stu student[10]
struct stu{
int num;
char name[20];
char sex;
};
struct stu student[10];
這個陣列有10個元素分別是student[0] 、student[1]、student[2]..........student[9]
(3)陣列元素的使用
1)student0].num =101;//用101給student陣列的第0個結構體變數的num賦值
2)使用字串操作函式:strcpy(student[1].name,"lucy");
step5:結構體指標
(1)結構體指標:即結構體的地址
(2)定義一個變數來存放這個地址,那這個變數就是結構體指標變數。
(3)結構體指標變數的定義方法:
.NOTE:結構體指標從兩方面來理解
(1)結構體和基本資料型別,原則上都是資料型別,一個是構造資料型別,一個是基本資料型別
(2)指標變數方面:基本資料型別int *a, 構造資料型別struct stu *ps
(4)struct stu{
int num;
char name[20];
};
struct stu * p;//定義了一個struct stu *型別的指標變數,變數名是p,p佔4個位元組,用來儲存結構體變數的地址編號
(5)使用: struct stu boy;
struct stu *p;
p=&boy;
訪問結構體變數的成員方法:
(1)boy.num=101;//可以,通過結構體變數名.成員名
(2)(*p).num=101;//可以,*p相當於p指向的變數boy
(3)p->num=101;//可以,指標->成員名
通過結構體指標來引用指標指向的結構體的成員,前提是指標必須先指向一個結構體變數。
step6:結構體記憶體對齊機制——記憶體對齊,提高定址效率
用空間來換時間,提高cpu讀取資料的效率
規則1:結構體分配記憶體時哪個基本型別的成員佔位元組數多,就以它的大小為單位開闢記憶體,
在gcc中出現了double型別的,例外
1:成員中只有char型資料 ,以1位元組為單位開闢記憶體。
2:成員中出現了short int 沒有更大位元組數的基本型別資料以2位元組為單位開闢記憶體
3、出現了int float 沒有更大位元組的基本型別資料的時候以4位元組為單位開闢記憶體。
4、出現了double型別的資料
情況1:
在vc裡,以8位元組為單位開闢記憶體。
情況2:
在gcc裡,以4位元組為單位開闢記憶體。
無論是那種環境,double型變數,佔8位元組。
注意:
如果在結構體中出現了陣列,陣列可以看成多個變數的集合。
如果出現指標的話,沒有佔位元組數更大的型別的,以4位元組為單位開闢記憶體。
在記憶體中儲存結構體成員的時候,按定義的結構體成員的順序儲存。
例1:struct stu{
char sex;
int age;
}lucy;
lucy的大小是4的倍數。
規則2:位元組對齊
1:char 1位元組對齊 ,即存放char型的變數,記憶體單元的編號是1的倍數即可。
2:short int 2位元組對齊 ,即存放short int 型的變數,起始記憶體單元的編號是2的倍數即可。
3:int 4位元組對齊 ,即存放int 型的變數,起始記憶體單元的編號是4的倍數即可
4:long int 在32位平臺下,4位元組對齊 ,即存放long int 型的變數,起始記憶體單元的編號是4的倍數即可
5:float 4位元組對齊 ,即存放float 型的變數,起始記憶體單元的編號是4的倍數即可
6:double
1.vc環境下
8位元組對齊,即存放double型變數的起始地址,必須是8的倍數,double變數佔8位元組
2.gcc環境下
4位元組對齊,即存放double型變數的起始地址,必須是4的倍數,double變數佔8位元組。
注意3:當結構體成員中出現數組的時候,可以看成多個變數。
注意4:開闢記憶體的時候,從上向下依次按成員在結構體中的位置順序開闢空間
例1:
struct stu{
char a;
short b;
int c;
}temp;
五、共用體(聯合體)的使用
step1:共用體的定義
(1)幾種不同型別的變數存到同一段記憶體單元中,幾個變數所使用空間相互重疊
(2)這種幾個不同的變數共同佔用一段記憶體的結構,在C語言中,被稱作“共用體”型別結構
(3)共用體所有成員佔有同一段地址空間
step2:共用體的大小
(1)共用體的大小是其佔記憶體長度最大的成員的大小
typedef union data{
short int i;
char ch;
float f;
}DATA;
DATA temp2;
共用體temp2佔4個位元組,即i、ch、f共用4個位元組
step3:共用體與大小端序
step6:共用體的本質
根據union固定首地址和union按最大需求開闢一段記憶體空間兩個特徵,可以發現,所有表面的定義都是虛的,所謂聯合體union,就是在記憶體給你劃了一個足夠用的空間,至於你怎麼玩~它不管~!(何止是union和struct,C不就是玩地址麼,所以使用C靈活,也容易犯錯)
給你首地址 + 記憶體空間,剩下的自己操作
六、列舉型別的應用
step1:列舉型別的定義
在C語言等計算機程式語言中是一種構造資料型別,它用於宣告一組命名的常數,當一個變數有幾種可能的取值時,可以將它定義為列舉型別
step2:列舉型別的特徵
(1) 列舉型是一個集合,集合中的元素(列舉成員)是一些命名的整型常量,元素之間用逗號,隔開。
(2) DAY是一個識別符號,可以看成這個集合的名字,是一個可選項,即是可有可無的項。
(3) 第一個列舉成員的預設值為整型的0,後續列舉成員的值在前一個成員上加1。
(4) 可以人為設定列舉成員的值,從而自定義某個範圍內的整數。
(5) 列舉型是預處理指令#define的替代。
(6) 型別定義以分號;結束。
step3:列舉宣告變數——列舉構造資料型別,與基本資料型別一致,都是資料型別
(1)列舉型別的定義和變數的宣告分開
(2)型別定義與變數宣告同時進行
(3)用typedef關鍵字型別重定義
.NOTE:同一個程式中不能定義同名的列舉型別,不同的列舉型別中也不能存在同名的命名常量
step4:使用列舉型別的變數
(1)先宣告變數,再對變數賦值
(2)宣告變數的同時賦初值
(3)定義型別的同時宣告變數,然後對變數賦值
(4)定義型別的同時宣告變數,然後對變數賦值
step5:enum與sizeof的千絲萬縷
列舉就是在其相應作用域內的一個識別符號而已,編譯器根本不知道什麼是列舉這個東西,列舉對於編譯器來說就是int型別的值而已,只不過是個常量int,列舉的一切行為表現都與一個普通的int值沒有區別,所以sizeof的值為4(32位機)。