c 複合資料型別 結構 列舉等
結構
由於多種內奸資料型別組成的一個整體,用於描述一個事物的各項資料。
設計結構體:
struct TypeName
{
型別 成員名;
...
};
注意:此時只是完成了資料型別的設計
相同的結構變數是可以賦值的 stu1 = stu;
定義結構變數:
一般結構體設計都是放在標頭檔案或者函式外,方便其他檔案和函式呼叫。
struct TyppeName 結構變數名;
初始化成員:
方法一:
struct TypeName 結構變數名 = {資料1,資料2 ...}
注意:一定要按照成員的的順序初始化
方法二:
struct TypeName 結構變數名 = { .成員名 = 資料1, .成員名 = 資料2, ... } 注意:可以不按照順序初始化,但是一定要加成員名
訪問成員:
結構變數,成員名;
結構指標-> 成員名;
使用堆記憶體儲存結構變數:
struct Student* stup =malloc(sizeof(struct TypeName));
賦值可以的 *stup = stu.con
結構體指標輸入
stup -> name(陣列不用取地址),&stup->id..
結構體指標輸出
類似於 stup->name,stup->id..
由於此時編譯時,堆記憶體還沒有分配(堆記憶體裡有解釋),所以編譯器還無法初始化,只能批量賦值,或單個賦值。
給結構型別重定義:
由於在c語言中struct關鍵詞無法省略,導致使用時麻煩,可以使用typedef關鍵詞結構重定義型別、
typedef struct typeName
{
..
}TypeName;
結構體的計算
系統為了快速的訪問結構的成員,會對結構的成員在記憶體排列時進行對齊和補齊,因此結構成員順序會影響結構的總位元組數,一般結構的總位元組數會 >= 所有成員的位元組數之和。
對齊:
假定第一個成員使用0地址,所有成員所使用的記憶體地址,必須被他的位元組數整除。
補齊
結構的總位元組數,必須是他最大成員的整數倍,如果不是則補充空位元組。
注意:在linux系統中計算對齊、補齊時,成員的位元組超過4時,則按照4自己計算,Windows正常。
struct Data { char ch1:4; char ch1:4; }
聯合:
也是由程式設計的一種資料型別,使用語法與結構一樣,只是成員的排列方式不同,所有成員共用一塊記憶體,一個成員的值發生變化,其他成員的值也會跟著變化。
特點:一塊記憶體對應多個識別符號,達到節約記憶體的目的,現在已經基本不用。
union TypeName
{
型別 成員名;
...
};
考點:
-
他的成員天然是對齊的,但是有記憶體補齊
-
使用聯合可以判斷大小端系統
系統的大小端:
小端系統:低位資料儲存在低位地址。
大段系統:地位資料儲存在高位地址。
一般個人計算機使用的是小端系統,大端伺服器、網路裝置使用的是大端,大端位元組序也叫網路位元組序。
列舉:
列舉是一種特殊的整型資料,他是把一個整型資料可能出現的值全部羅列出來並取一個有意義的名字(列舉值),除此之外不應該 再使用其他的值,以此保證資料的安全性,提高程式的可讀性。
enum Direction {Up, Down, Left, Right};
設計好的列舉型別,可以下定義列舉變數,而列舉變數只能賦值為列舉值,以此保證資料的安全性。
注意:編譯器為了速度,並不會檢查檢查列舉變數的賦值
列舉值是常量,可以使用在case語句的後面,不用再寫字面值常量,從而提高程式的可讀性
列舉值在不指定的情況下,第一個預設為0,之後的逐漸加1,可以單個指定。可以定義匿名列舉,只使用列舉值。
預處理指令
程式設計師所編寫的c程式碼並不能直接被編譯,而是需要一段程式預先翻譯成標準的c程式碼,負責處理的程式就叫前處理器,翻譯的過程就叫做預處理,被翻譯的程式碼就叫做預處理指令,所有預處理指令都是以#開頭
include 把標頭檔案插入當前檔案中
#include<> 從系統指定的路徑下查詢標頭檔案,並插入當前檔案中。
#include"" 先從當前路徑下查詢標頭檔案,如果沒有再從系統指定路徑下查詢標頭檔案,然後再插入當前檔案中。
define 巨集定義指令
定義號巨集常量
#define 巨集名 (字面值)
注意:末尾不要加分號
作用:用識別符號來替代字面值資料,從而提高程式碼的可讀性,可擴充套件性。
程式碼在預處理時所使用的巨集名會被替換成字面值。
#define 巨集名(a,b,c) (a+b+c)
不是真正的函式,而是在使用了帶引數的巨集,預處理時使用了帶參巨集的位置替換成巨集名後面的語句,所提供的的引數也會被替換到語句中的位置。
優點:
- 不是真正的函式呼叫,沒有引數傳遞過程,也沒有返回值
- 不限制引數型別,任何型別都可以使用,程式碼的通用性強
缺點:
- 沒有型別檢查,安全性低
- 過多使用會造成程式碼冗SW餘,導致程式碼段增大,浪費記憶體。
- 可能會有二義性(多加點括號)
定義巨集函式要注意的問題:
- 給每個引數加一個小括號,避免產生二義性
- 使用小括號、大括號包含整個巨集函式程式碼,進行保護
- 巨集函式不能換行可以使用續行符 \ 來分行一下,但是還是一行
- 巨集函式引數不要使用自變運算子。
練習
定義一個交換兩個變數的巨集函式,要任何型別的變數都可以使用
the first way
#define swap(a,b,type) { \ type t=a; \ a=b; \ b=t; \ }
the second way
#define swap(a,b) {typeof(a) t=a; a=b; b=t;}