結構體,列舉,聯合。

2021-08-20 06:41:58 字數 4238 閱讀 5335

今天我們來學習一下結構體,列舉以及聯合等知識。

一。首先從結構體開始,結構體與陣列一樣都是聚合型別。

1.結構體的宣告:

struct tag

variable-list;

tag(1)可以省略(2)見名思意(3)盡量不省略。

member-list:不能為空。

variable-list:可以省略。例如:描述一位學生

struct stu

;

特殊的宣告:在宣告時可以不完全的宣告。比如:
struct

x;struct

a[20],*p;

p=&x;

這兩個結構在宣告時都省略了結構體標籤tag。但p=&a;這是非法的,因為編譯器會把上面的兩個宣告當成兩個完全不同的兩個型別。所以是非法的。

二。結構體的成員:可以是標量,陣列,指標,甚至是其他結構體。那我們該如何訪問這些成員呢?

結構體成員的訪問:結構變數的成員通過點操作符(.)訪問的。

struct s s;

strcpy(s.name,"zhangsan"); //使用.訪問name成員。

s.age=20; //使用.訪問age成員。

結構體訪問指向變數的成員時有時候我們得到的不是乙個結構體變數,而是指向乙個結構體的指標。這時就該如下訪問:
struct s

s;void print(struct s* ps)

三。結構的自引用。例子:
struct node

;

(1)不可行,(2)可行。

四。結構體變數的定義和初始化。同時,結構體不能被整體賦值,這點和陣列一樣。

struct point

p1; //宣告型別的同時定義變數p1.

struct point p2; //定義結構體變數。

struct point p3=; //初始化:定義變數時賦值。

struct stu //型別說明

;struct stu =; //初始化

struct node

n1=,null}; //結構體巢狀初始化

struct node n2=,null}; //結構體巢狀初始化

五。結構體內存對齊。

1,為什麼存在記憶體對齊呢?(1)平台原因(移植原因):不是所有的硬體平台都能訪問任意位址上的任意資料的;某些硬體平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常。(2)效能原因:資料結構(尤其是棧)應該盡可能的在自然邊界上對齊。原因在於,為了訪問未對齊的記憶體,處理器需要作兩次記憶體訪問;而對齊的記憶體訪問僅需要依次訪問。                  

2.掌握結構體的對齊規則:

(1)第乙個成員在與結構體變數偏移量為0的位址處。(2)其它成員變數要對齊到某個數字(對齊數)的整數倍的位址處。對齊數=編譯器預設的乙個對齊數與該成員大小的較小值。vs預設8,linux預設4.(3)結構體總大小為最大對齊數(每個成員變數都有乙個對齊數)的整數倍。(4)如果巢狀了結構體的情況,巢狀的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含巢狀結構體的對齊數)的整數倍。

總體來說:結構體的記憶體對齊就是拿空間換取時間的做法。例題:

練習一

struct s1

;printf("%d\n",sizeof(struct s1)); //1+3+4+1=9%4!=0,所以答案是12.

練習二

struct s2

;printf("%d\n",sizeof(struct s2)); //1+1+2+4=8%4==0,所以答案是8.

練習三

struct s3

;printf("%d\n",sizeof(struct s3)); //8+1+3+4=16%8==0,所以答案是16.

練習四

struct s4

;printf("%d\n",sizeof(struct s3)); //8+1+7+16=32%8==0,所以答案是32.

只要學會這四道題,就證明你差不多掌握了記憶體對齊了。

六。結構體傳參:跟陣列不一樣,它傳參時不會發生降維。

struct s

;struct s s=,1000};

//結構體傳參

void print1(struct s s)

//結構體傳參

void print2(struct s* ps)

int main()

很明顯print2函式是更好的,節省時間。原因:函式傳參的時候,引數是需要壓棧的。如果傳遞乙個結構體物件時,結構體過大,引數壓棧的系統開銷比較大,所以會導致效能的下降。

七。位段:位段的宣告和結構是類似的,只有兩個不同(1)位段的成員必須是int . unsigned int 或signed int,就是說成員要一樣。(2)位段的成員名後邊有乙個冒號和乙個數字。

struct a

;

位段的記憶體分配:(1)位段的成員可以是int  unsigned int  signed int  或者是char(屬於整形家族)型別。(2)位段的空間上是按照需要以四個位元組(int)或者乙個位元組(char)的方式來開闢的。(3)位段涉及很多不確定因素,位段是不跨台的,注重可移植的程式應該避免使用位段。

位段的跨平台問題:(1)int位段被當成有符號數還是無符號數是不確定的。(2)位段中最大位的數目不能確定(16位機器最大為16,32位機器最大為32,寫成27,在16位機器會出現問題)(3)位段中的成員在記憶體中從左向右分配,還是從右向左分配未定義。(4)當乙個結構包含兩個位段,第二個位段成員比較大,無法容納於第乙個位段剩餘的位時,是捨棄剩餘的位還是利用,這是不確定的。總結:跟結構相比,尾端可以到達同樣的效果,但是可以很好的節省空間,但是有跨平台的問題存在。

八。列舉:顧名思義,把可能的取值一一枚舉。

1.列舉型別的定義

enum day  //星期

;enum *** //性別

;enum color //顏色

;

以上定義的都是列舉型別,{}中的內容是列舉常量。

2.列舉的優點:(1)增加**的可讀性和可維護性(2)和#define定義的識別符號比較列舉有型別檢查,更加嚴謹。(3)防止了命名汙染。(4)便與除錯。(5)使用方便,一次可定義多個常量。

3.列舉的使用。

enum color  //顏色

;enum color clr=green; //只能拿列舉常量給列舉常量賦值,才不會出現型別的差異。

九。聯合(共用體):聯合也是一種特殊的自定義型別,這種型別定義的變數包含了一系列的成員,特徵是這些成員公用同一塊空間(所以聯合也叫共用體)。

1.聯合型別的宣告

union un

;union un un; //聯合變數的定義。

printf("%d\n",sizeof(un));//計算聯合變數的大小。

2.聯合的特點:聯合的成員時共用同一塊記憶體空間的,這樣的乙個聯合變數的大小,至少是最大成員的大小(因為聯合至少得有能力儲存最大的那個成員)

3.聯合的大小。

(1)聯合的大小至少是最大成員的大小

(2)當最大成員大小不是最大對齊數的整數倍時,就要對齊到最大對齊數的整數倍。舉例:

#include#includeunion un1

;union un2

;int main()

答案是第乙個是8,第二個是16.解析:un1中,c[5]佔5個,但是5不是最大對齊數4的整數倍,所以5+3=8.所以聯合的大小為8.

同理第二個中,short[7]佔14個,大於14且還是4的整倍數的數就是16,所以答案是16.

以上就是我的總結,謝謝**。



結構體,列舉,聯合

結構體 1.結構體的建立 1 在構建結構體之前,必須要對結構體進行宣告。例 struct student 描述乙個學生,student為標籤 此處的分號不能丟,此處也可寫變數 2 成員訪問 2.1在 1 中的 struct student 相當於型別,比如 int型,struct student s...

結構體 聯合 列舉

一般的,在宣告乙個結構提示要使用struct關鍵字,例如 建立乙個學生 struct stu char name 20 名字 int age 年齡 char 5 性別 char id 20 學號 分號不能丟結構體得特殊宣告 沒有結構體名 structx 沒有結構體的標籤,就不能在結構體建立完成之後再...

結構體列舉與聯合

基本介紹 struct是結構體的關鍵字,它將一些相關聯的資料打包成乙個整體,這些相關聯的資料可以是不同的型別。它們被稱為結構體的成員,結構體的成員可以是標量 陣列 指標 或者是其他結構體。結構的宣告 假設我們要建立學生檔案,要納入學生的姓名,年齡和性別三個內容。那麼我們可以通過建立乙個結構體來實現這...