天天看點

C和指針 (pointers on C)——第十章:結構體和聯合(上)

第十章 結構和聯合

這個部分先介紹了.運算符,可以供直接通路,還介紹了->運算符,它代替結構體指針的間接通路操作(*struct).xxx

這一章新手了解起來不算太難,沒有學過作業系統的話了解位段、對齊等概念會有一些問題。

越發的說明了指針和記憶體絕對是C的核心。

總結:

結構聲明列出了結構包含的成員清單,不同類型的值可以存儲在一起。

不同的結構聲明即使他們的成員清單相同也被認為是不同的類型。

聲明結構時使用typedef建立一種新類型是一個好方法。

typedef struct

{

int a;

char b;

float c;

}simple;

跟結構标簽的結果幾乎相同。差別在于simple現在是一個類型名而不是結構體,以後聲明就是下面這個樣子。

simple x;

simple y[20], *z;

結構不能包含類型也是這個結構的成員,否則在配置設定位址的時候,會出現無窮大。但是可以包含一個指向這個結構的指針。

這個常常用在鍊式結構中。為了聲明兩個結構,每個結構都包含一個指向對方的指針的成員。

初始化的時候可以由一個花括号包圍的值清單進行初始化。

編譯器為一個結構變量的成員配置設定記憶體時要滿足它們的邊界對齊要求。在實作結構存儲的邊界對齊時,可能會浪費部分空間。根據邊界對齊要求降序排列結構成員可以最大限度地減少結構存儲中浪費的記憶體空間。

如果想要減少對齊造成的損失,一般來說聲明的過程中要降序排列。可以利用offstof宏(stddef.h)+sizeof來找個更好的辦法。

結構可以作為形參傳遞給函數,也可以作為傳回值傳回但是絕對不提倡!!!嚴重浪費記憶體空間。

最好形參和傳回值都用指針,如果怕修改結構本身,那麼就加個const!

位段個人不是了解很深,了解來看是可以将長度為奇數的值包裝在一起節省空間。

Union和struct是兩個不同的故事。所有Union的成員都存儲于同一個記憶體位置。也可以進行初始化,但是初始化必需與聯合第一個成員類型比對。

關于初始化:

union{

int a;

float b;

char c[4];

} x = {5};

這樣就把x.a初始為5。

警告:

1、具有相同成員清單的結構聲明産生不同類型。

這就像函數一樣,跟聲明關系很大。

2、使用typedef為一個自引用的結構定義名字時應該小心。

自引用一定要記住,要引用指針。

3、向函數傳遞結構參數是低效的。

要對記憶體的形參進行拷貝,這份拷貝放在記憶體裡實在是太浪費空間。

程式設計提示:

1、typedef聲明放在頭檔案中。到是用到就#include回來。

2、結構成員的最佳排列形式并不一定就是考慮邊界對齊而浪費記憶體空間最少的那種排列方式。

很顯然,為了對齊,有時候你不得不打亂聲明的順序,進而導緻可讀性的降低。

3、把位段成員顯式得聲明為signed int 或者 unsigned int類型。

4、位段是不可抑制的。

5、位段使源代碼中位的表達式更加清楚。

問題:

1、成員和數組元素有什麼差別?

成員可以具備不同的類型,數組不行。

2、結構名和數組名有什麼不同?

數組名是一個指針常量。但是結構名就是個标簽tag,跟class名類似,沒有執行個體的話,是不會對其配置設定記憶體的。

3、結構的聲明:

struct tag{member-list } variable-list;

tag、member-list、variable-list三者必需有二。