C語言編程C++自定義個性化類型
自定義類型
結(jié)構(gòu)體
結(jié)構(gòu)是一些值的集合,這些值稱為成員變量。結(jié)構(gòu)的每個成員可以是不同類型的變量
聲明一個結(jié)構(gòu)體類型
//聲明一個學(xué)生類型,是想通過學(xué)生類型來創(chuàng)建學(xué)生變量(對象) //描述學(xué)生就得有屬性啥的。名字,電話,性別,年齡 struct Stu { char name[20];//名字 char tele[12];//電話 char sex[10];//性別 int age;//年齡 }; struct Stu s3;//創(chuàng)建全局結(jié)構(gòu)體變量 int main() { struct Stu s1; struct Stu s2;//創(chuàng)建結(jié)構(gòu)體變量 return 0; }
特殊聲明
在聲明結(jié)構(gòu)的時候,可以不完全的聲明。
沒有結(jié)構(gòu)體標(biāo)簽
匿名結(jié)構(gòu)體類型
要清楚一點匿名結(jié)構(gòu)體是個類型不占用空間的,就好像int一樣,他們沒有創(chuàng)建一個變量是不會開辟空間的,所以類型不占用空間就沒有銷毀不銷毀這一說,只有有了空間才會有銷毀不銷毀這一說,類型就好像圖紙,變量才是真正要蓋的房子
struct { char name[20];//名字 char tele[12];//電話 char sex[10];//性別 int age;//年齡 }stu;//直接接結(jié)構(gòu)體變量,匿名的時候后面就把變量給創(chuàng)建好,不然之后也用不到這個結(jié)構(gòu)名,因為沒有結(jié)構(gòu)體名字怎么創(chuàng)建變量呢
匿名結(jié)構(gòu)體指針類型
struct { char name[20];//名字 char tele[12];//電話 char sex[10];//性別 int age;//年齡 }* pstu;//這時pstu就變成匿名結(jié)構(gòu)體指針了
結(jié)構(gòu)體自引用
在結(jié)構(gòu)中包含一個類型為該結(jié)構(gòu)本身的成員是否可以呢?
所以節(jié)點(Node)就出來了
一塊表示數(shù)據(jù)一塊表示地址
struct Node { int data; //數(shù)據(jù)域 struct Node* next; //指針域 };
這就是結(jié)構(gòu)體自引用 自己類型里的變量找到同類型的另外一個對象
注意
所以對于結(jié)構(gòu)體的自引用是不能省略自己的結(jié)構(gòu)體標(biāo)簽,下面就是解決方案
typedef struct Node { int data; //數(shù)據(jù)域 struct Node* next; //指針域 }Node;
結(jié)構(gòu)體變量的定義和初始化
struct Stu { char name[20];//名字 char tele[12];//電話 char sex[10];//性別 int age;//年齡 }; struct Stu s3;//創(chuàng)建全局結(jié)構(gòu)體變量 int main() { struct Stu s1 = {"zhuzhongyuan","13151732661","nan",22};//(定義)創(chuàng)建結(jié)構(gòu)體變量s1并初始化 printf("%s %s %s %d",s1.name,s1.tele,s1.sex,s1.age); return 0; }
結(jié)構(gòu)體內(nèi)存對齊
現(xiàn)在我們深入討論一個問題:計算結(jié)構(gòu)體的大小。
這也是一個特別熱門的考點:結(jié)構(gòu)體內(nèi)存對齊
#include<stdio.h> //內(nèi)存對齊 //結(jié)構(gòu)體內(nèi)存對齊 struct S2 { int a; char b; char c; }; struct S1 { char b; int a; char c; }; int main() { printf("%d\n", sizeof(struct S1)); printf("%d\n", sizeof(struct S2)); return 0; }
結(jié)構(gòu)體內(nèi)存對齊的規(guī)則
- 結(jié)構(gòu)體的第一個成員永遠(yuǎn)放在結(jié)構(gòu)體起始位置偏移量為0的位置
- 結(jié)構(gòu)體成員從第二成員開始,總是放在一個對齊數(shù)的整數(shù)倍處
- 對齊數(shù)是什么呢是編譯器默認(rèn)的對齊數(shù)和變量自身大小的較小值注意一下 linux沒有默認(rèn)對齊數(shù)vs下默認(rèn)對齊數(shù)是8
- 結(jié)構(gòu)體的總大小必須是各個成員的對齊數(shù)中最大那個對齊數(shù)的整數(shù)倍
- 如果嵌套了結(jié)構(gòu)體的情況,嵌套的結(jié)構(gòu)體對齊到自己的最大對齊數(shù)的整數(shù)倍處,結(jié)構(gòu)體的整體大小就是所有最大對齊數(shù)(含嵌套結(jié)構(gòu)體的對齊數(shù))的整數(shù)倍
幾個練習(xí)
為什么存在內(nèi)存對齊
1.平臺原因(移植原因)
不是所有的硬件平臺都能訪問任意地址上的任意數(shù)據(jù),某些平臺只能在某些地址某些特定類型的數(shù)據(jù),否則拋出硬件異常
2.性能原因
數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能地在自然邊界上對齊,原因在于,為了訪問未對齊的內(nèi)存,處理器需要作兩次內(nèi)存訪問,而對齊的訪問僅需要一次訪問
總體來說
結(jié)構(gòu)體內(nèi)存對齊就是拿空間換取時間的做法,形象的說就是浪費了內(nèi)存,換來了方便
解決
那在設(shè)計結(jié)構(gòu)體的時候,我們既要滿足對齊,又要節(jié)省空間,如何做到:
讓占用空間小的成員盡量集中在一起。
修改默認(rèn)對齊數(shù)
vs默認(rèn)對齊數(shù)是8
我們可以通過#pragma pack()來修改默認(rèn)對齊數(shù)
默認(rèn)設(shè)置對齊數(shù)是2的幾次方
offsetof宏的實現(xiàn)
計算結(jié)構(gòu)體中某變量相對于首地址的偏移
offsetof原格式
結(jié)構(gòu)體傳參
值傳遞
址傳遞
如何選擇
1.函數(shù)傳參的時候,參數(shù)是需要壓棧,會有時間和空間上的系統(tǒng)開銷。
2.如果傳遞一個結(jié)構(gòu)體對象的時候,結(jié)構(gòu)體過大,參數(shù)壓棧的的系統(tǒng)開銷比較大,所以會導(dǎo)致性能的下降。
結(jié)論: 結(jié)構(gòu)體傳參的時候,要傳結(jié)構(gòu)體的地址。
位段
什么是位段
位段的聲明和結(jié)構(gòu)體類似,有兩個不同
1.位段的成員必須是int,unsiged int 或 signed int
2.位段的成員后面有一個冒號和一個數(shù)字
位段的內(nèi)存分配 位段的成員可以是int, unsigned int,signed int,或者是char(屬于整形家族)類型位段的空間上是按照需要以4個字節(jié)(int)或者1個字節(jié)(char)的方式來開辟的位段涉及很多不確定因素,位段是不跨平臺的,注重可移植的程序應(yīng)該避免使用位段
位段的跨平臺問題 int 位段被當(dāng)成有符號數(shù)還是無符號數(shù)是不確定的。位段中最大位的數(shù)目不能確定。(16位機器最大16,32位機器最大32,寫成27,在16位機器會出問題。位段中的成員在內(nèi)存中從左向右分配,還是從右向左分配標(biāo)準(zhǔn)尚未定義。當(dāng)一個結(jié)構(gòu)包含兩個位段,第二個位段成員比較大,無法容納于第一個位段剩余的位時,是舍棄剩余的位還是利用,這個也是不確定的。 總結(jié):
跟結(jié)構(gòu)相比,位段可以達(dá)到同樣的效果,可以很好的節(jié)省空間,但是有跨平臺的問題存在。
位段的應(yīng)用
枚舉
如果我們沒有對枚舉常量進行初始化的話,他們是默認(rèn)加一的
我們常量分為4種
1.字面常量
2.const修飾的常變量
3.#號定義的標(biāo)識符常量
4.枚舉常量
這里我們就講枚舉常量
枚舉常量是不可以改的,只能初始化
那枚舉怎么用呢
枚舉的優(yōu)點
我們可以使用 #define 定義常量,為什么非要使用枚舉? 枚舉的優(yōu)點:
增加代碼的可讀性和可維護性和#define定義的標(biāo)識符比較枚舉有類型檢查,更加嚴(yán)謹(jǐn)。防止了命名污染(封裝)便于調(diào)試
而define是不可以的,因為define是完完全全替換的,在代碼中看到GREEN什么的直接替換為1,代碼中就沒有GREEN的概念了,完完全全的替換
使用方便,一次可以定義多個常量 簡易計算器
#include<stdio.h> enum Option { exit, add, sub, mul, div }; void menu() { printf("*********************\n"); printf("****1.add 2.sub****\n"); printf("****3.mul 4.div****\n"); printf("**** 0.exit ****\n"); printf("*********************\n"); } int main() { int input = 0; int a = 0; int b = 0; int c = 0; do { menu(); printf("請選擇:>"); scanf("%d",&input); printf("請輸入兩個操作數(shù):>"); scanf("%d%d", &a, &b); switch (input) { case add: c = a + b; printf("%d\n", c); break; case sub: c = a - b; printf("%d\n", c); break; case mul: c = a * b; printf("%d\n", c); break; case div: if (b == 0) { printf("分子不能為0\n"); break; } else { c = a / b; printf("%d\n", c); break; } default: break; } } while (input); return 0; }
聯(lián)合(共用體)
聯(lián)合類型的定義
聯(lián)合也是一種特殊的自定義類型 這種類型定義的變量也包含一系列的成員,特征是這些成員公用同一塊空間(所以
聯(lián)合也叫共用體)。
聯(lián)合類型的聲明
聯(lián)合的特點
聯(lián)合的成員是共用同一塊內(nèi)存空間的,這樣一個聯(lián)合變量的大小,至少是最大成員的大?。ㄒ驗槁?lián)合至少得有能力保存最大的那個成員)
判斷當(dāng)前機器的大小端存儲【】
之前學(xué)過一個方法
#include<stdio.h> int main() { int a = 1; //0x 00 00 00 01 //低 -------------> 高 //01 00 00 00 小端存儲 //00 00 00 01 大端存儲 //想辦法拿到a的第一個字節(jié) char* pc = (char*)&a; if (*pc == 1) { printf("小端存儲"); } else { printf("大端存儲"); } return 0; }
現(xiàn)在學(xué)到共用體正好利用他的特殊情況
#include<stdio.h> union Un { char c; int i; }; int main() { union Un u = { 0 }; u.i = 1; if (u.c == 1) { printf("小端存儲"); } else { printf("大端存儲"); } return 0; }
聯(lián)合大小的計算
聯(lián)合的大小至少是最大成員的大小。
當(dāng)最大成員大小不是最大對齊數(shù)的整數(shù)倍的時候,就要對齊到最大對齊數(shù)的整數(shù)倍。
以上就是C語言編程C++自定義個性化類型的詳細(xì)內(nèi)容,更多關(guān)于C++自定義類型的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
關(guān)于C++11的統(tǒng)一初始化語法示例詳解
C++之前的初始化語法很亂,有四種初始化方式,而且每種之前甚至不能相互轉(zhuǎn)換,但從C++11出現(xiàn)后就好了,所以這篇文章主要給大家介紹了關(guān)于C++11的統(tǒng)一初始化語法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-10-10C語言結(jié)構(gòu)體數(shù)組常用的三種賦值方法(包含字符串)
C語言只有在定義字符數(shù)組的時候才能用“=”來初始化變量,其它情況下是不能直接用“=”來為字符數(shù)組賦值的,下面這篇文章主要給大家介紹了關(guān)于C語言結(jié)構(gòu)體數(shù)組常用的三種賦值方法,需要的朋友可以參考下2022-06-06用標(biāo)準(zhǔn)c++實現(xiàn)string與各種類型之間的轉(zhuǎn)換
這個類在頭文件中定義, < sstream>庫定義了三種類:istringstream、ostringstream和stringstream,分別用來進行流的輸入、輸出和輸入輸出操作。另外,每個類都有一個對應(yīng)的寬字符集版本2013-09-09