結構體
結構體的概念
★ 計算機程序設計語言都有數據類型的概念
★ 數據類型一般有基本類型和用戶自定義類型
★ 在c語言中,基本類型有int型、double型、char型等等。
★ 而結構體類型則屬於用戶自定義類型,是由基本類型組合而成的複雜類型。
★ 定義好的結構體類型可以像基本類型一樣去定義此類型的變量。
定義結構體類型和定義結構體類型變量
★ 我們先看看定義結構體類型的一般形式:
struct 結構體標示符
{
結構體元素;
};
如下:
struct StructDemo
{
char c;
int i;
};
★ 定義結構體類型變量方式一:
定義類型的同時定義變量,如下:
struct StructDemo
{
char c;
int i;
}sd1,sd2;
這樣就定了兩個結構體變量sd1,sd2了,這兩個變量的類型是struct StructDemo類型。
★ 定義結構體類型變量方式二:
定義類型之後定義變量,如下:
struct StructDemo
{
char c;
int i;
};
這個定義說明我們已經定義完成了一個新的類型,這個類型說明符就是struct StructDemo。
所以我們可以用此來定義變量了。如下:
struct StructDemo sd1,sd2;
★ 定義結構體類型變量方式三:
類型說明符重命名的方法。
學習C語言的朋友,對typedef估計不會陌生的,用它可以給類型說明符一個別名,此名字和原來的名字具有同樣意義。
如:typedef int zhengxing;
那麼int i和zhengxing i是一樣的意思。
同樣的道理也可運用於我們自定義的數據類型。
typedef struct StructDemo SD;
SD sd1,sd2;
結構體類型的初始化
★ 定義的同時初始化,如:
struct StructDemo sd1 = {‘A’,10},sd2 = {‘B’,12};
SD sd1 = {‘A’,10},sd2 = {‘B’,12};
struct StructDemo
{
char c;
int i;
} sd1 = {‘A’,10},sd2 = {‘B’,12};
★ 定義之後再初始化,如:
sd1 = {‘A’,10};
sd2 = {‘B’,12};
sd1.c = ‘D’;
sd1.i = 20;
結構體運用舉例1
我們將上面所說的結構體的定義、定義結構體類型變量、初始化用一個實際的程序來呈現,我現在這臺機器上裝的linux系統是OpenSuSe,所以我們打開OpenSuSe,打開終端,利用vim編輯程序StructDemo01.c如下:
編譯運行如下:
結構體的大小問題
計算機程序語言中的數據類型在使用時在計算機中都會佔有一定的內存空間,結構體類型是用戶自定義類型,也屬於數據類型的一種,那麼它在計算機內存中佔有的空間大小又是什麼情況呢?下面我們來看一下。
我們定義一個結構體類型如下:
Struct StuctDemo
{
char c;
int i;
};
我們先嚐試估計一下這個結構體類型所佔有的內存空間的大小,我們知道一個char類型佔有1個字節,而一個int類型佔有4個字節,那麼我們是否可以認爲這個結構體類型佔有的內存空間爲5個字節呢?
下面我們用程序來驗證這個問題,這也是我們學習計算機所有的常用手法,快捷方便準確。
在舉例子之前我們說一下一個關鍵字sizeof,sizeof可以告訴我們一個數據類型佔有的內存空間到底有多大,具體形式:sizeof(類型說明符)得到字節數。
下面我們創建一個c語言源程序文件命名爲Demo02.c,我們用vim打開編輯如下:
我們編譯運行:
結果大出我們所料,結果竟然是8,爲什麼不是5呢?
現代計算機中內存空間都是按照byte劃分的,從理論上講似乎對任何類型的變量的訪問可以從任何地址開始,但實際情況是在訪問特定類型變量的時候經常在特 定的內存地址訪問,這就需要各種類型數據按照一定的規則在空間上排列,而不是順序的一個接一個的排放,這就是對齊。
各個硬件平臺對存儲空間的處理上有很大的不同。一些平臺對某些特定類型的數據只能從某些特定地址開始存取。比如有些架構的CPU在訪問 一個沒有進行對齊的變量的時候會發生錯誤,那麼在這種架構下編程必須保證字節對齊.其他平臺可能沒有這種情況,但是最常見的是如果不按照適合其平臺要求對 數據存放進行對齊,會在存取效率上帶來損失。比如有些平臺每次讀都是從偶地址開始,如果一個int型(假設爲32位系統)如果存放在偶地址開始的地方,那 麼一個讀週期就可以讀出這32bit,而如果存放在奇地址開始的地方,就需要2個讀週期,並對兩次讀出的結果的高低字節進行拼湊才能得到該32bit數 據。
其實字節對齊的細節和具體編譯器實現相關,但一般而言,滿足三個準則: 1) 結構體變量的首地址能夠被其最寬基本類型成員的大小所整除; 2) 結構體每個成員相對於結構體首地址的偏移量都是成員大小的整數倍,如有需要編譯器會在成員之間加上填充字節;例如上面第二個結構體變量的地址空間。 3) 結構體的總大小爲結構體最寬基本類型成員大小的整數倍,如有需要編譯器會在最末一個成員之後加上填充字節。
看了這段文字相信我們很容易理解爲什麼是8而不是5了,正是因爲字節對齊的需要。