晉江論壇匿名區(qū)青島seo排名收費
=========================================================================
相關(guān)代碼gitee自取:C語言學(xué)習(xí)日記: 加油努力 (gitee.com)
?=========================================================================
接上期:
學(xué)C的第二十九天【字符串函數(shù)和內(nèi)存函數(shù)的介紹(二)】_高高的胖子的博客-CSDN博客
?=========================================================================
? ? ? ? ? ? ? ? ? ? ?
1 . 結(jié)構(gòu)體
(1). 結(jié)構(gòu)體的基礎(chǔ)知識:
? ? ? ? ? ? ?
結(jié)構(gòu)是一些值的集合,這些值稱為成員變量。
結(jié)構(gòu)的每個成員可以是不同類型的變量。
? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ??
(2). 結(jié)構(gòu)體的聲明:
? ? ? ? ? ? ? ??
struct tag? ? ? ? ?
{????????????????????????
????????????????member - list;
}variable - lest;
? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ??
struct? --? 結(jié)構(gòu)體標(biāo)簽
tag? --? 自定義結(jié)構(gòu)名
?member - list? --? 成員列表
variable - lest? --? 結(jié)構(gòu)體變量列表
? ? ? ? ? ? ? ? ? ? ?
實例:
? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ??
(3). 特殊的聲明:
? ? ? ? ? ? ??
匿名結(jié)構(gòu)體:在聲明結(jié)構(gòu)時,可以不完全地聲明,即聲明時省略掉了結(jié)構(gòu)體標(biāo)簽(tag)
? ? ? ? ? ? ? ? ? ? ?
實例:
? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ??
(4). 結(jié)構(gòu)的自引用:
? ? ? ? ? ?
在結(jié)構(gòu)中包含一個類型為該結(jié)構(gòu)本身的成員(類似遞歸?)
? ? ? ? ? ? ? ??
實例:
? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ??
(5). 結(jié)構(gòu)體變量的定義和初始化:
? ? ? ? ? ? ? ??
兩種 定義 實例:
? ? ? ? ? ? ? ? ?
兩種 初始化 實例:
? ? ? ? ? ? ? ? ?
結(jié)構(gòu)體成員列表包含另一個結(jié)構(gòu)體 實例:
? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ??
(6). 結(jié)構(gòu)體內(nèi)存對齊(重點):
? ? ? ? ? ? ??
運用于計算結(jié)構(gòu)體大小
? ? ? ? ? ?
? ? ? ? ? ?
結(jié)構(gòu)體的對齊規(guī)則:
? ? ? ? ??
1. 第一個成員在與結(jié)構(gòu)體變量偏移量為0的地址處。
? ? ? ? ? ? ? ? ? ? ??
2. 其他成員變量要對齊到某個數(shù)字(對齊數(shù))的整數(shù)倍的地址處。
- 對齊數(shù) = 編譯器默認(rèn)的一個對齊數(shù) 與 該成員大小?兩者中的較小值。
- VS中默認(rèn)的值為8,Linux中沒有默認(rèn)對齊數(shù),對齊數(shù)就是成員自身的大小
? ? ? ? ? ? ? ? ? ? ?
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)存訪問僅需要一次訪問。
? ? ? ? ? ?
? ? ? ? ? ?
總體來說:
結(jié)構(gòu)體的內(nèi)存對齊是拿空間來換取時間的做法。
在設(shè)計結(jié)構(gòu)體的時候,我們既要滿足對齊,又要節(jié)省空間;
讓占用空間小的成員盡量集中在一起。
? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ??
(7). 修改默認(rèn)對齊數(shù):
? ? ? ? ? ? ? ??
結(jié)構(gòu)在對齊方式不合適的時候,我們可以自己更改默認(rèn)對齊數(shù)。
使用 #pragma 預(yù)處理指令,修改默認(rèn)對齊數(shù)
示例:
? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ??
(8). 結(jié)構(gòu)體傳參:
? ? ? ? ? ? ? ?
函數(shù)傳參的時候,參數(shù)是需要壓棧,會有時間和空間上的系統(tǒng)開銷。
如果傳遞一個結(jié)構(gòu)體對象的時候,結(jié)構(gòu)體過大,
參數(shù)壓棧的的系統(tǒng)開銷比較大,會導(dǎo)致性能的下降。
所以結(jié)構(gòu)體傳參的時候,最好傳結(jié)構(gòu)體的地址。
示例:
? ? ? ? ? ??
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
? ? ? ? ? ? ?
2 . 位段(位域)
(1). 什么是位段:
? ? ? ? ? ? ??
位段的聲明和結(jié)構(gòu)體是類似的,
有兩個不同:
1.位段的成員必須是 int、unsigned int 或signed int 。
2.位段的成員名后邊有一個冒號和一個數(shù)字。
? ? ? ? ? ??
這個數(shù)字指這個成員變量所占的二進(jìn)制位數(shù),
限定該成員變量的空間,節(jié)省內(nèi)存。
? ? ? ? ? ? ?
位段的大小為所有的“數(shù)字”相加后所需字節(jié)數(shù),
如果不夠字節(jié)存儲,則加一個單位的字節(jié)。
示例:
? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ??
(2). 位段的內(nèi)存分配:
? ? ? ? ? ? ? ? ?
- 位段的成員可以是 int, unsigned int, signed int 或者是 char (屬于整形家族)類型
- 位段的空間上是按照需要以4個字節(jié)( int )或者1個字節(jié)( char )的方式來開辟的。
- 位段涉及很多不確定因素,位段是不跨平臺的,注重可移植的程序應(yīng)該避免使用位段。
? ? ? ? ? ? ? ? ? ? ?
示例:
? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ??
(3). 位段的跨平臺問題:
? ? ? ? ? ? ?
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)包含兩個位段,第二個位段成員比較大,無法容納于第一個位段剩余的位時,是舍棄剩余的位還是利用,這是不確定的。
? ? ? ? ? ? ?
總結(jié):
跟結(jié)構(gòu)相比,位段可以達(dá)到同樣的效果,并且可以很好的節(jié)省空間,
但是有跨平臺的問題存在。
? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ??
(4). 位段的運用:
? ? ? ? ? ? ??
在網(wǎng)絡(luò)底層的實現(xiàn)中,
在對數(shù)據(jù)進(jìn)行包裝時的結(jié)構(gòu)就是使用了位段這種形式來分裝的。
? ? ? ? ? ?
(ip數(shù)據(jù)包的格式:)
? ? ? ? ? ??
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
? ? ? ? ? ? ?
3 . 枚舉
枚舉顧名思義?一一 列舉
把可能的取值列出來 一一 列舉
? ? ? ? ? ?
比如我們現(xiàn)實生活中:
一周的星期一到星期日是有限的7天,可以一一列舉
性別有:男、女、保密,也可以一一列舉
月份有12個月,也可以一一列舉
? ? ? ? ? ?
這時就可以使用枚舉了。
? ? ? ? ? ?
(1). 枚舉類型的定義:
? ? ? ? ? ??
下列示例定義的 enum Color 是枚舉類型。
{}中的內(nèi)容是枚舉類型的可能取值,也叫 枚舉常量 。
這些可能取值都是有值的,默認(rèn)從0開始,依次遞增1,
當(dāng)然在聲明枚舉類型的時候也可以賦初值。
? ? ? ? ? ? ??
示例:
? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ??
(2). 枚舉的優(yōu)點:
? ? ? ? ? ? ? ?
我們可以使用 #define 定義常量,為什么非要使用枚舉?
? ? ? ? ??
枚舉的優(yōu)點:
1. 增加代碼的可讀性和可維護(hù)性
2. 和#define定義的標(biāo)識符比較枚舉有類型檢查,更加嚴(yán)謹(jǐn)
3. 只能拿枚舉常量給枚舉變量賦值,不會出現(xiàn)類型的差異
3. 便于調(diào)試
4. 使用方便,一次可以定義多個常量
? ? ? ? ? ??
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
? ? ? ? ? ? ?
4 . 聯(lián)合(共用體)
(1). 聯(lián)合類型的定義:
? ? ? ??
聯(lián)合也是一種特殊的自定義類型
這種類型定義的變量也包含一系列的成員,
特征是這些成員公用同一塊空間(所以聯(lián)合也叫共用體)。
? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ??
(2). 聯(lián)合的特點:
? ? ? ??
聯(lián)合的成員是共用同一塊內(nèi)存空間的,
這樣一個聯(lián)合變量的大小,至少是最大成員的大小
,因為聯(lián)合至少得有能力保存最大的那個成員。
? ? ? ? ? ? ??
示例:
(因為聯(lián)合體成員都共用一個空間,所以同一時間只能使用一個聯(lián)合體成員)
? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ??
(3). 聯(lián)合大小的計算:
? ? ? ??
聯(lián)合的大小至少是最大成員的大小。
當(dāng)最大成員大小不是最大對齊數(shù)的整數(shù)倍的時候,
就要對齊到最大對齊數(shù)的整數(shù)倍。
? ? ? ? ? ? ??
示例: