自定義類型
結構體
結構是一些值的集合,這些值稱為成員變量。結構的每個成員可以是不同類型的變量
聲明一個結構體類型
//聲明一個學生類型,是想通過學生類型來創建學生變量(對象) //描述學生就得有屬性啥的。名字,電話,性別,年齡 struct Stu { char name[20];//名字 char tele[12];//電話 char sex[10];//性別 int age;//年齡 }; struct Stu s3;//創建全局結構體變量 int main() { struct Stu s1; struct Stu s2;//創建結構體變量 return 0; }
特殊聲明
在聲明結構的時候,可以不完全的聲明。
沒有結構體標簽
匿名結構體類型
要清楚一點匿名結構體是個類型不占用空間的,就好像int一樣,他們沒有創建一個變量是不會開辟空間的,所以類型不占用空間就沒有銷毀不銷毀這一說,只有有了空間才會有銷毀不銷毀這一說,類型就好像圖紙,變量才是真正要蓋的房子
struct { char name[20];//名字 char tele[12];//電話 char sex[10];//性別 int age;//年齡 }stu;//直接接結構體變量,匿名的時候后面就把變量給創建好,不然之后也用不到這個結構名,因為沒有結構體名字怎么創建變量呢
匿名結構體指針類型
struct { char name[20];//名字 char tele[12];//電話 char sex[10];//性別 int age;//年齡 }* pstu;//這時pstu就變成匿名結構體指針了
結構體自引用
在結構中包含一個類型為該結構本身的成員是否可以呢?
所以節點(Node)就出來了
一塊表示數據一塊表示地址
struct Node { int data; //數據域 struct Node* next; //指針域 };
這就是結構體自引用 自己類型里的變量找到同類型的另外一個對象
注意
所以對于結構體的自引用是不能省略自己的結構體標簽,下面就是解決方案
typedef struct Node { int data; //數據域 struct Node* next; //指針域 }Node;
結構體變量的定義和初始化
struct Stu { char name[20];//名字 char tele[12];//電話 char sex[10];//性別 int age;//年齡 }; struct Stu s3;//創建全局結構體變量 int main() { struct Stu s1 = {"zhuzhongyuan","13151732661","nan",22};//(定義)創建結構體變量s1并初始化 printf("%s %s %s %d",s1.name,s1.tele,s1.sex,s1.age); return 0; }
結構體內存對齊
現在我們深入討論一個問題:計算結構體的大小。
這也是一個特別熱門的考點:結構體內存對齊
#include<stdio.h> //內存對齊 //結構體內存對齊 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; }
結構體內存對齊的規則
- 結構體的第一個成員永遠放在結構體起始位置偏移量為0的位置
- 結構體成員從第二成員開始,總是放在一個對齊數的整數倍處
- 對齊數是什么呢是編譯器默認的對齊數和變量自身大小的較小值注意一下 linux沒有默認對齊數vs下默認對齊數是8
- 結構體的總大小必須是各個成員的對齊數中最大那個對齊數的整數倍
- 如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處,結構體的整體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍
幾個練習
為什么存在內存對齊
1.平臺原因(移植原因)
不是所有的硬件平臺都能訪問任意地址上的任意數據,某些平臺只能在某些地址某些特定類型的數據,否則拋出硬件異常
2.性能原因
數據結構(尤其是棧)應該盡可能地在自然邊界上對齊,原因在于,為了訪問未對齊的內存,處理器需要作兩次內存訪問,而對齊的訪問僅需要一次訪問
總體來說
結構體內存對齊就是拿空間換取時間的做法,形象的說就是浪費了內存,換來了方便
解決
那在設計結構體的時候,我們既要滿足對齊,又要節省空間,如何做到:
讓占用空間小的成員盡量集中在一起。
修改默認對齊數
vs默認對齊數是8
我們可以通過#pragma pack()來修改默認對齊數
默認設置對齊數是2的幾次方
offsetof宏的實現
計算結構體中某變量相對于首地址的偏移
offsetof原格式
結構體傳參
值傳遞
址傳遞
如何選擇
1.函數傳參的時候,參數是需要壓棧,會有時間和空間上的系統開銷。
2.如果傳遞一個結構體對象的時候,結構體過大,參數壓棧的的系統開銷比較大,所以會導致性能的下降。
結論: 結構體傳參的時候,要傳結構體的地址。
位段
什么是位段
位段的聲明和結構體類似,有兩個不同
1.位段的成員必須是int,unsiged int 或 signed int
2.位段的成員后面有一個冒號和一個數字
位段的內存分配 位段的成員可以是int, unsigned int,signed int,或者是char(屬于整形家族)類型位段的空間上是按照需要以4個字節(int)或者1個字節(char)的方式來開辟的位段涉及很多不確定因素,位段是不跨平臺的,注重可移植的程序應該避免使用位段
位段的跨平臺問題 int 位段被當成有符號數還是無符號數是不確定的。位段中最大位的數目不能確定。(16位機器最大16,32位機器最大32,寫成27,在16位機器會出問題。位段中的成員在內存中從左向右分配,還是從右向左分配標準尚未定義。當一個結構包含兩個位段,第二個位段成員比較大,無法容納于第一個位段剩余的位時,是舍棄剩余的位還是利用,這個也是不確定的。 總結:
跟結構相比,位段可以達到同樣的效果,可以很好的節省空間,但是有跨平臺的問題存在。
位段的應用
枚舉
如果我們沒有對枚舉常量進行初始化的話,他們是默認加一的
我們常量分為4種
1.字面常量
2.const修飾的常變量
3.#號定義的標識符常量
4.枚舉常量
這里我們就講枚舉常量
枚舉常量是不可以改的,只能初始化
那枚舉怎么用呢
枚舉的優點
我們可以使用 #define 定義常量,為什么非要使用枚舉? 枚舉的優點:
增加代碼的可讀性和可維護性和#define定義的標識符比較枚舉有類型檢查,更加嚴謹。防止了命名污染(封裝)便于調試
而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("請輸入兩個操作數:>"); 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; }
聯合(共用體)
聯合類型的定義
聯合也是一種特殊的自定義類型 這種類型定義的變量也包含一系列的成員,特征是這些成員公用同一塊空間(所以
聯合也叫共用體)。
聯合類型的聲明
聯合的特點
聯合的成員是共用同一塊內存空間的,這樣一個聯合變量的大小,至少是最大成員的大小(因為聯合至少得有能力保存最大的那個成員)
判斷當前機器的大小端存儲【】
之前學過一個方法
#include<stdio.h> int main() { int a = 1; //0x 00 00 00 01 //低 -------------> 高 //01 00 00 00 小端存儲 //00 00 00 01 大端存儲 //想辦法拿到a的第一個字節 char* pc = (char*)&a; if (*pc == 1) { printf("小端存儲"); } else { printf("大端存儲"); } return 0; }
現在學到共用體正好利用他的特殊情況
#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; }
聯合大小的計算
聯合的大小至少是最大成員的大小。
當最大成員大小不是最大對齊數的整數倍的時候,就要對齊到最大對齊數的整數倍。
以上就是C語言編程C++自定義個性化類型的詳細內容,更多關于C++自定義類型的資料請關注服務器之家其它相關文章!
原文鏈接:https://blog.csdn.net/diandengren/article/details/120376471