欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言深入探究自定義類型之結(jié)構(gòu)體與枚舉及聯(lián)合

 更新時間:2022年05月12日 09:57:32   作者:Iceevov  
今天我們來學(xué)習(xí)一下自定義類型,自定義類型包括結(jié)構(gòu)體、枚舉、聯(lián)合體,小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考

1.結(jié)構(gòu)體

1.1結(jié)構(gòu)體類型的聲明

結(jié)構(gòu)是一些值的集合,這些值稱為成員變量。結(jié)構(gòu)的每個成員可以是不同類型的變量

這里給大家舉個列子演示一下:

//定義一個學(xué)生的結(jié)構(gòu)體
typedef struct Stu
{
	char name[20];//姓名
	int age;//年齡
	char sex[5];//性別
	char id[15];//學(xué)號
}Stu;//分號不能丟

在這個結(jié)構(gòu)體里面我們定義了學(xué)生的名字,年齡,性別,學(xué)號這些變量,這樣的變量就叫做成員變量。

結(jié)構(gòu)的成員可以是標(biāo)量、數(shù)組、指針,甚至是其他結(jié)構(gòu)體。

這里的typedef是將結(jié)構(gòu)體重命名為Stu。

1.2結(jié)構(gòu)的自引用

上面我們說到了成員變量也可以為結(jié)構(gòu)體,我們不妨大膽的猜想一下,結(jié)構(gòu)體內(nèi)可以包含一個類型為自身結(jié)構(gòu)體的成員嗎?

答案當(dāng)然是可以的,不過有需要我們注意的地方下面給大家用代碼的形式演示一下:

//1.錯誤引用
struct Node
{
	int data;
	struct Node next;
};
//2.正確引用
struct Node
{
	int data;//數(shù)據(jù)
	struct Node* next;//地址
};

對比上面的代碼正確的代碼比錯誤的多一個' * ',代表傳地址我們來分析一下錯誤的地方,穿了一個結(jié)構(gòu)體進(jìn)去,那么我們這個結(jié)構(gòu)體的大小是多少呢,顯然沒辦法計算,結(jié)構(gòu)題內(nèi)套一個結(jié)構(gòu)體,然后這個結(jié)構(gòu)體又套一起進(jìn)去,類似無條件遞歸,編譯器也會報錯。那么我們來看正確的代碼,

結(jié)構(gòu)體分為兩部分,一部分存放數(shù)據(jù),一部分存放地址,當(dāng)我需要的時候我們根據(jù)地址找到內(nèi)嵌的結(jié)構(gòu)體,這樣就可以講這些結(jié)構(gòu)體串起來了,當(dāng)我們訪問到最后一個時,我們只需要給它一個NULL就停止了,這樣是不是就很完美了呢。

1.3結(jié)構(gòu)體變量的定義和初始化

有了結(jié)構(gòu)體類型怎么定義和初始化結(jié)構(gòu)體變量呢,其實很簡單,給大家演示一下:

struct Point
{
	int x;
	int y;
}p1;             //1.聲明類型的同時定義變量p1
struct Point p2; //2.定義結(jié)構(gòu)體變量p2
//3.初始化:定義變量的同時賦初值
struct Point p3 = { x , y };

1.4結(jié)構(gòu)體內(nèi)存對齊

我們知道int的大小為4個字節(jié),char的大小為1個字節(jié),每個數(shù)據(jù)類型都有大小,那么結(jié)構(gòu)體大小又是多少呢,該怎么計算呢?

這里需涉及到一個知識點就是內(nèi)存對齊:

1. 第一個成員在與結(jié)構(gòu)體變量偏移量為0的地址處。

2. 其他成員變量要對齊到某個數(shù)字(對齊數(shù))的整數(shù)倍的地址處。 對齊數(shù) = 編譯器默認(rèn)的一個對齊數(shù) 與 該成員大小的較小值。 VS中默認(rèn)的值為8

3. 結(jié)構(gòu)體總大小為最大對齊數(shù)(每個成員變量都有一個對齊數(shù))的整數(shù)倍。

4. 如果嵌套了結(jié)構(gòu)體的情況,嵌套的結(jié)構(gòu)體對齊到自己的最大對齊數(shù)的整數(shù)倍處,結(jié)構(gòu)體的整 體大小就是所有最大對齊數(shù)(含嵌套結(jié)構(gòu)體的對齊數(shù))的整數(shù)倍

文字的形式可能有點抽象,下面用圖來給大家演示一下:

為什么存在內(nèi)存對齊?

大部分的參考資料都是如是說的:

1. 平臺原因(移植原因): 不是所有的硬件平臺都能訪問任意地址上的任意數(shù)據(jù)的;某些硬件平臺只能在某些地址處取某些特定類型的數(shù)據(jù),否則拋出硬件異常。

2. 性能原因: 數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能地在自然邊界上對齊。 原因在于,為了訪問未對齊的內(nèi)存,處理器需要作兩次內(nèi)存訪問;而對齊的內(nèi)存訪問僅需要一次訪問

總體來說就是拿空間換時間的做法。

那我們在設(shè)計結(jié)構(gòu)體的時候想要節(jié)省空間就要做到,讓占用空間小的成員盡量集中在一起。

1.5結(jié)構(gòu)體傳參

我們知道在傳參的時候有兩種方式,傳值和傳址。那么在結(jié)構(gòu)體傳參的時候我們通常采用結(jié)構(gòu)體地址傳參。

函數(shù)傳參的時候,參數(shù)是需要壓棧,會有時間和空間上的系統(tǒng)開銷。

如果傳遞一個結(jié)構(gòu)體對象的時候,結(jié)構(gòu)體過大,參數(shù)壓棧的的系統(tǒng)開銷比較大,所以會導(dǎo)致性能的

下降。

代碼演示如下:

struct S
{
	int data[1000];
	int num;
};
struct S s = { {1,2,3,4},1000 };//初始化賦值
void print1(struct S* pc)用struct S*的指針接收
{
	printf("%d\n", pc->num);
}
int main()
{
	print1(&s);//傳地址
	return 0;
}

1.6結(jié)構(gòu)體實現(xiàn)位段(位段的填充&可移植性)

位段的聲明和結(jié)構(gòu)是類似的,有兩個不同:

1.位段的成員必須是 int、unsigned int 或signed int 。

2.位段的成員名后邊有一個冒號和一個數(shù)字

如下圖,A就是一個位段

struct A
{
int _a:2;
int _b:5;
int _c:10;
int _d:30;
};

位段的內(nèi)存分配:

1. 位段的成員可以是 int unsigned int signed int 或者是 char (屬于整形家族)類型

2. 位段的空間上是按照需要以4個字節(jié)( int )或者1個字節(jié)( char )的方式來開辟的。

3. 位段涉及很多不確定因素,位段是不跨平臺的,注重可移植的程序應(yīng)該避免使用位段

位段的跨平臺問題:

1. int 位段被當(dāng)成有符號數(shù)還是無符號數(shù)是不確定的。

2. 位段中最大位的數(shù)目不能確定。(16位機器最大16,32位機器最大32,寫成27,在16位機 器會出問題。

3. 位段中的成員在內(nèi)存中從左向右分配,還是從右向左分配標(biāo)準(zhǔn)尚未定義。

4. 當(dāng)一個結(jié)構(gòu)包含兩個位段,第二個位段成員比較大,無法容納于第一個位段剩余的位時,是 舍棄剩余的位還是利用,這是不確定的。

2.枚舉

枚舉就是列舉,例如一周有七天可以列舉,三原色可以列舉,性別可以列舉

2.1枚舉類型的定義

enum Color//顏色
{
	RED,//0
	GREEN,//1
	BLUE//2
};

這里定義的 enum Color 就是是枚舉類型。

{}中的內(nèi)容是枚舉類型的可能取值,也叫 枚舉常量 。

這些可能取值都是有值的,默認(rèn)從0開始,一次遞增1,當(dāng)然在定義的時候也可以賦初值,RED=1,GREEN=2,BLUE=100,都是可以的。

2.2枚舉的優(yōu)點

1. 增加代碼的可讀性和可維護(hù)性

2. 和#define定義的標(biāo)識符比較枚舉有類型檢查,更加嚴(yán)謹(jǐn)。

3. 防止了命名污染(封裝)

4. 便于調(diào)試

5. 使用方便,一次可以定義多個常量

3.聯(lián)合

3.1聯(lián)合類型的定義

聯(lián)合也是一種特殊的自定義類型

這種類型定義的變量也包含一系列的成員,特征是這些成員公用同一塊空間(所以聯(lián)合也叫共用體)。 比如:

//聯(lián)合類型的聲明
union Un
{
char c;
int i;
};
//聯(lián)合變量的定義
union Un un;
//計算連個變量的大小
printf("%d\n", sizeof(un));//計算出來結(jié)果為4

3.2聯(lián)合的特點

聯(lián)合的成員是共用同一塊內(nèi)存空間的,這樣一個聯(lián)合變量的大小,至少是最大成員的大小(因為聯(lián)合至少得有能力保存最大的那個成員)。

上面的例子在聯(lián)合體Un中最大的成員為int占4個字節(jié),所以聯(lián)合體Un的大小也為4個字節(jié)。

3.3聯(lián)合大小的計算

聯(lián)合的大小至少是最大成員的大小。

當(dāng)最大成員大小不是最大對齊數(shù)的整數(shù)倍的時候,就要對齊到最大對齊數(shù)的整數(shù)倍。

下面兩個例子中的計算方法和上面內(nèi)存圖解差不多,大家可以研究一下。

union Un1
{
char c[5];
int i;
};
union Un2
{
short c[7];
int i;
};
//下面輸出的結(jié)果是什么?
printf("%d\n", sizeof(union Un1));//8
printf("%d\n", sizeof(union Un2));//16

到此這篇關(guān)于C語言深入探究自定義類型之結(jié)構(gòu)體與枚舉及聯(lián)合的文章就介紹到這了,更多相關(guān)C語言結(jié)構(gòu)體內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論