C語言自定義數據類型的結構體、枚舉和聯合詳解

結構體基礎知識

首先結構體的出現是因為我們使用C語言的基本類型無法滿足我們的需求,比如我們要描述一本書,就需要書名,作者,價格,出版社等等一系列的屬性,無疑C語言的基本數據類型無法解決,所以就出現瞭最重要的自定義數據類型,結構體

首先我們創建一個書的結構體類型來認識一下

struct Book
{
	char name[20];
	char author[20];
	int price;
};

首先是struct是結構體關鍵字,用來告訴編譯器你這裡聲明的是一個結構體類型而不是其他的東西,然後是Book是結構體標簽,而關鍵字加標簽就是你結構體類型的名字,即struct Book 是你結構體類型的名字,然後看到結構體裡面的內容,即大括號裡面的內容,有兩個字符數組和一個整型變量,一個數組用來存放書的名字,一個數組用來存放書的作者,整型變量用來存放書的價格,在類型聲明中需要多少變量就放入多少變量,需要什麼變量就放入什麼變量,而這些變量就是結構體的成員變量,成員變量可以是不同的類型註意,結構體聲明的末尾分號不可省略,到此我們已經有瞭基本的認識,接下來我們來使用一下結構體類型,既然是類型,那麼肯定就可以拿來創建變量,我們就拿上面那個描述書的結構體類型試一下

可以看到使用規則和基本數據類型之類的並無太大區別,唯一區別就是結構體初始化一定要用大括號將初始化的內容括起來,如果不是初始化那麼就需要先訪問他的成員才能一一賦值,這裡我們是在創建結構體的時候對它進行瞭初始化,放入瞭一些數據,小夥伴們能夠清楚的看到屏幕上輸出瞭這些數據,其中通過結構體變量訪問結構體成員的時候使用瞭點號. 這個點號是結構體成員訪問操作符,通過它我們就可以拿到結構體的成員,看完之後小夥伴們最好是自己也敲一下試試,代碼能力是練出來的,初學時一定要多敲多練,到此結構體基礎知識我們就介紹完瞭,接下來我們來進階一下。

結構體進階知識

首先結構體是可以嵌套定義的,像下面這樣

結構體計算大小

結構體在分配內存的時候,會發生結構體內存對齊,對齊規則如下:

  • 第一個成員在與結構體變量偏移量為0的地址處。
  • 其他成員變量要對齊到某個數字(對齊數)的整數倍的地址處。
  • 結構體總大小為最大對齊數(每個成員變量都有一個對齊數)的整數倍。
  • 如果嵌套瞭結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍。

知道瞭規則我們來用一下,下面這個結構體的大小不考慮對齊的情況隻需要6byte的空間就能存下所有數據,但是考慮到內存對齊就需要12byte的空間,這就足足多瞭一倍的空間,那麼為什麼還需要這個對齊的規則呢,原因大致有以下兩點:

  • 平臺原因(移植原因): 不是所有的硬件平臺都能訪問任意地址上的任意數據的;某些硬件平臺隻能在某些地址處取某些特定類型的數據,否則拋出硬件異常。
  • 性能原因: 數據結構(尤其是棧)應該盡可能地在自然邊界上對齊。 原因在於,為瞭訪問未對齊的內存,處理器需要作兩次內存訪問;而對齊的內存訪問僅需要一次訪問。
struct S1
{
 char c1;//1 byte
 int i;//4byte
 char c2;//1byte
};
printf("%d\n", sizeof(struct S1));

總的來說,結構體的內存對齊是拿空間來換取時間的做法,結構體就介紹的差不多瞭,下面我們來看看枚舉

枚舉基礎知識

枚舉顧名思義就是把所有的可能性 一 一 列舉出來,比如說一個星期分為星期一,星期二到星期天七天我們就可以使用枚舉

enum Day
{
 Mon,
 Tues,
 Wed,
 Thur,
 Fri,
 Sat,
 Sun
};

和結構體一樣首先是枚舉關鍵字enmu然後是枚舉的標簽Day,然後是成員,但是和結構體不同的是,枚舉的成員是常量,而且是整型常量,並且不賦值的話是有默認值,而且默認值是向下依次遞增1的,我們來看看就知道瞭

可以看到不主動賦值的情況下,下一個比上一個大1,並且第一個默認為0,看看賦值瞭的

枚舉就這麼簡單,接下來看看聯合體

聯合體

聯合體是由關鍵字union和標簽定義的,和結構體和枚舉是一樣的定義方式,和前面兩個不一樣的是,一個聯合體隻有一塊內存空間,這句話什麼意思呢,就相當於隻開辟最大的變量的內存,其他的變量都在那個變量占據空間(空間可以被重疊占用)看看下面的圖片

上面黑色和紅色的重疊部分就是共用的區域,兩個變量都能使用它,這個東西很少用的就不多講瞭,唯一記住的就是,聯合體可以求當前編譯環境是大端字節序存儲模式還是小端字節序存儲模式,至於怎麼求,看看下面這個代碼,應該很好理解

#include<stdio.h>
union Un{
	char ch;
	int n;
};
int main()
{
	union Un un;
	un.n = 1;
	//小端 01 00 00 00
	//大端 00 00 00 01
	if (un.ch == 1) {//取出第一個字節的內容判斷
		printf("小端");
	}
	else {
		printf("大端");
	}
	return 0;
}

這個東西理解不瞭也沒啥關系,一般用不上。

一些小結和建議

1.盡量不要使用聯合體,因為一次修改會導致多個數據被修改,容易出現不可預料的問題.

2.結構體內存對齊一定要學會計算,雖然實際可能用不上,但是可能會面試中出現.

3.結構體中還有一個叫字段的知識點,形式如下,這個東西現在用於傳輸數據,後端開發一般用不上,所以博主沒講,感興趣的小夥伴就自行百度瞭解一下吧

4.枚舉一般搭配switch語句使用,可以提高代碼的可讀性。

寫在最後的話

到此這篇關於C語言自定義數據類型的結構體、枚舉和聯合詳解的文章就介紹到這瞭,更多相關C語言自定義數據類型內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: