1.1、結構體宣告
結構體是一些值的集合,這些值稱為成員變數,這些值可以是不同的型別
struct tag
variable-list;
#include #include //結構體是一些值的集合,這些值稱為成員變數,結構的每個成員可以是不同型別的變數。
//一般宣告
struct stu
;//特殊宣告
//匿名結構體型別,下面兩個結構體的宣告的時候省略掉了結構體標籤(tag)
struct
x;struct
a[20], *p;
int main()
當結構體宣告的時候省略了結構體標籤,編譯器會把兩個相同型別值組成的結構體宣告為兩個不同的型別,是非法操作。
1.2、結構體的自引用
#include #include //結構體中包含乙個型別為該結構體本身的成員
struct node
;//typedef struct node
//node;
int main()
1.3、結構體變數的定義和初始化
#include #include struct point
p1; //宣告型別的同時定義變數p1
//賦初值
struct point p3 = ;
struct student //型別宣告
;struct student s = ;//初始化
struct node3 //結構體巢狀初始化
n1 = , null };
struct node3 n2 = , null };//結構體巢狀初始化
int main()
1.4、結構體內存對齊
結構體對齊規則:1、第乙個成員與結構體變數偏移量為0的位址處。
2、其他成員變數對齊到某個數字(對齊數)的整數倍的位址處
對齊數 = 編譯器預設的乙個對齊數與該成員大小的較小值
注:vs預設對齊數為8,linux的預設對齊數為4
3、結構體總大小為最大對齊數(每個成員變數都有乙個對齊數)的整數倍
4、如果巢狀了結構體,巢狀結構體對齊到自己最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含巢狀結構體的對齊數)的整數倍。
為什麼存在記憶體對齊:1、移植原因:不是所有的硬體平台都能訪問任意位址上的任意資料,某些硬體平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常。
2、效能原因:資料結構應該盡可能在自然邊界對齊,為了訪問未對齊的記憶體,處理器需要做兩次記憶體訪問,而對齊的記憶體訪問僅需要一次訪問。
結構體內存對齊選擇空間換時間,提高效能
#include #include /*
結構體的對齊規則:
1、第乙個成員與結構體變數偏移量為0的位址處。
2、其他成員變數對齊到某個數字(對齊數)的整數倍的位址處
對齊數 = 編譯器預設的乙個對齊數與該成員大小的較小值
注:vs預設對齊數為8,linux的預設對齊數為4
3、結構體總大小為最大對齊數(每個成員變數都有乙個對齊數)的整數倍
4、如果巢狀了結構體,巢狀結構體對齊到自己最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含巢狀結構體的對齊數)的整數倍。
*/struct s1
;struct s2
;struct s3
;struct s4
;int main()
我們在設計結構體的時候,我們既要滿足對齊,又要節省空間
我們採取占用空間小的成員盡量集中在一起。
1.5、修改預設對齊數
使用 #pragma pack(位元組數)修改預設對齊數
#include #include //修改預設對齊數為8
#pragma pack(8)
struct s1
;//取消設定預設對齊數,還原為預設
#pragma pack()
//修改預設對齊數為1
#pragma pack(1)
struct s2
;//取消設定預設對齊數,還原為預設
#pragma pack()
int main()
1.6、結構體傳參
結構體傳參的時候傳結構體位址,防止在引數壓棧的時候系統開銷過大,導致效能下降
#include #include //結構體傳參首選傳位址,這樣結構體過大的情況下可以防止引數壓棧過程中開銷過大,導致效能下降的問題
struct qwe
;struct qwe q = , 1000 };
//結構體傳參
void print1(struct qwe q)
void print2(struct qwe *q)
int main()
2.1、什麼是位段
位段和結構體類似1、未斷電額成員必須是int、unsigned int或signed int
2、位段的成員名後面跟所佔的位數
#include #include //1、位段的成員必須是int、unsigned int或signed int
//2、位移的成員名後邊有乙個冒號和乙個數字。
//3、與結構體類似。
struct a
;int main()
2.2、位段的記憶體分配
1、位段的成員可以是int、unsigned int、signed int或者char(屬於整形家族)型別2.3、位段的跨平台問題2、位段的空間上是按照需要以4個位元組(int)或1個位元組(char)的方式來開闢的
3、位段的使用要避免跨平台
1、int位段在不同的編譯器不能確定是不是有無符號型別使用位段可以達到和結構體相同的效果,比結構體節省空間,但是存在跨平台問題。2、位段中最大位的數目不能確定。
3、位段的成員在記憶體中是從左向右還是從右向左定義尚未定義
4、當乙個結構包含兩個位段,第二個位段成員比較大,無法容納第乙個位段的剩餘位段是利用還是捨棄不確定
3.1、列舉型別的定義
列舉型別的定義:{}中內容是列舉型別的可能取值,叫列舉常量
#include #include //enum預設從0開始,依次遞增1
//列舉的優點:
/*1、增加**的可讀性和可維護性
2、和#define定義的識別符號比較,列舉有型別檢查,更加嚴謹
3、防止了命名汙染(封裝)
4、便與除錯,使用過方便,一次可以定義多個常量
*/enum day//星期
;enum ***//性別
;enum color//顏色
;int main()
列舉的優點:
1、增加**的可讀性和可維護性
2、和#define定義的識別符號比較,列舉有型別檢查,更加嚴謹
3、防止了命名汙染(封裝)
4、便與除錯,使用過方便,一次可以定義多個常量
3.2、列舉的使用
#include #include enum color1
;int main()
4.1、聯合的特點
聯合的成員共用一塊記憶體空間,這樣乙個聯合變數的大小,至少是最大成員的大小。聯合的使用:
#include #include //聯合體變數宣告
union un
;int main()
聯合的特點:
#include #include union un
;int main()
4.2、聯合體大小的計算
聯合體大小的計算規則:1、聯合的大小至少是最大成員的大小
2、當最大成員大小不是最大對齊數的整數倍的時候,就要對齊到最大對齊數的整數倍。
#include #include union un1
;union un2
;int main()
自定義型別 結構體,位段,列舉,聯
1 結構體 1 結構體的宣告 結構體中的每個成員可以是不同型別的變數 例如 描述乙個學生 struct stu 2 結構體的自引用 struct node 3 結構體變數的定義和初始化 宣告型別的同時定義變數p1 struct point p1 初始化 struct point p2 4 結構體內存...
自定義型別 結構體 位段 列舉 聯合
include include include 1 結構體 結構是一些值的集合,這些值稱為結構體成員,結構體的每個成員可以是不同型別的變數 struct stu 結構體的自引用 struct node 錯誤的,結構體內不能包含結構體自身 struct node 正確 指標是四個位元組 結構體內存對齊...
自定義型別 結構體 位段 列舉 聯合
1 結構體基礎知識 定義 不同或相同型別元素的集合 宣告 直接上例子會更清楚 成員 可以是變數 陣列 指標甚至其它結構體成員。struct stu 分號不能丟特殊宣告 匿名結構體型別,並不建議省略結構體型別名,知道有這麼回事就好了 struct x 注意 有n個結構體就有n種型別,即使兩個結構體成員...