自定義型別詳解(結構體,位段,列舉, 聯合)

2021-10-03 06:06:32 字數 4662 閱讀 1243

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、位段的空間上是按照需要以4個位元組(int)或1個位元組(char)的方式來開闢的

3、位段的使用要避免跨平台

2.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種型別,即使兩個結構體成員...