C語(yǔ)言自定義類型超詳細(xì)梳理之結(jié)構(gòu)體 枚舉 聯(lián)合體
一、什么是結(jié)構(gòu)體
結(jié)構(gòu)是一些值的集合,這些值稱為成員變量。結(jié)構(gòu)的每個(gè)成員可以是不同類型的變量。
//結(jié)構(gòu)體聲明
struct tag //struct:結(jié)構(gòu)體關(guān)鍵字,tag:標(biāo)簽名,合起來(lái)是結(jié)構(gòu)體類型(類型名)
{
member - list;//大括號(hào)里面的是結(jié)構(gòu)體成員變量
}variable - list;//結(jié)構(gòu)體變量
1.結(jié)構(gòu)體實(shí)現(xiàn)

代碼如下:
#include<stdio.h>
struct Book
{
char name[20];//書(shū)名
int price;//價(jià)格
char id[20];//書(shū)號(hào)
}b2,b3,b4;//結(jié)構(gòu)體變量(全局變量)
int main()
{ //結(jié)構(gòu)體變量(局部變量)
struct Book b1 = { "c和指針", 30, "1112345454" };//結(jié)構(gòu)體初始化
struct Book* pb = &b1;
printf("%s %d %s\n",b1.name,b1.price,b1.id );
printf("%s %d %s\n", pb->name, pb->price, pb->id);//指針?lè)绞酱蛴?
return 0;
}
2.匿名結(jié)構(gòu)體類型
//匿名結(jié)構(gòu)體類型
struct
{
int a;
char b;
float c;
}s;//直接永匿名結(jié)構(gòu)體類型創(chuàng)建了一個(gè)變量s,匿名結(jié)構(gòu)體只能用一次
struct
{
int a;
char b;
float c;
}*ps;//匿名結(jié)構(gòu)體的指針
結(jié)構(gòu)在聲明的時(shí)候省略掉了結(jié)構(gòu)體標(biāo)簽(tag)就叫做匿名結(jié)構(gòu)體。
那么問(wèn)題來(lái)了?
int main()
{
ps = &s;//不合法,編譯器會(huì)把上面的兩個(gè)聲明當(dāng)成完全不同的兩個(gè)類型。
所以是非法的
}
3.結(jié)構(gòu)體自引用
struct Node
{
int data;
struct Node* next;
}
//結(jié)構(gòu)體自引用
//這個(gè)節(jié)點(diǎn)能夠找到同類型的下一個(gè)節(jié)點(diǎn),這就叫結(jié)構(gòu)體的自引用,我自己能找到同類型跟自己同類型的下一個(gè)元素就叫結(jié)構(gòu)體的自引用。
//結(jié)構(gòu)體的自引用實(shí)現(xiàn):在結(jié)構(gòu)體里面包含同類型的結(jié)構(gòu)體的指針。
4.結(jié)構(gòu)體的內(nèi)存對(duì)齊
首先得掌握結(jié)構(gòu)體的對(duì)齊規(guī)則:
1. 第一個(gè)成員在與結(jié)構(gòu)體變量偏移量為0的地址處。
2. 其他成員變量要對(duì)齊到某個(gè)數(shù)字(對(duì)齊數(shù))的整數(shù)倍的地址處。 對(duì)齊數(shù) = 編譯器默認(rèn)的一個(gè)對(duì)齊數(shù) 與 該成員大小的較小值。 VS中默認(rèn)的值為8
3. 結(jié)構(gòu)體總大小為最大對(duì)齊數(shù)(每個(gè)成員變量都有一個(gè)對(duì)齊數(shù))的整數(shù)倍。
4. 如果嵌套了結(jié)構(gòu)體的情況,嵌套的結(jié)構(gòu)體對(duì)齊到自己的最大對(duì)齊數(shù)的整數(shù)倍處,結(jié)構(gòu)體的整 體大小就是所有最大對(duì)齊數(shù)(含嵌套結(jié)構(gòu)體的對(duì)齊數(shù))的整數(shù)倍。

我們來(lái)算一下上面結(jié)構(gòu)體S內(nèi)存大小為什么是12個(gè)字節(jié)

我用到編譯器是vs,vs編譯器的默認(rèn)對(duì)齊數(shù)是8.
1.結(jié)構(gòu)體的第一個(gè)成員,放在結(jié)構(gòu)體變量在內(nèi)存中儲(chǔ)存位置的0偏移處開(kāi)始。
2.從第二個(gè)成員往后的所有成員,都放在一個(gè)對(duì)齊數(shù)(成員的大小和默認(rèn)對(duì)齊數(shù)的較小值)的整數(shù)的整數(shù)倍的地址處。
3.結(jié)構(gòu)體的總大小是結(jié)構(gòu)體的所有成員的對(duì)齊數(shù)中最大的那個(gè)對(duì)齊數(shù)的整數(shù)倍。
5.結(jié)構(gòu)體位段
位段的聲明和結(jié)構(gòu)是類似的,有兩個(gè)不同:
1.位段的成員必須是 int、unsigned int 或signed int 。
2.位段的成員名后邊有一個(gè)冒號(hào)和一個(gè)數(shù)字。

假設(shè)我們用二進(jìn)制的方式來(lái)表示性別,分為男、女、保密??梢杂?0、01、10分別表示。這樣我們連一個(gè)字節(jié)的大小都用不到,但如果我們創(chuàng)建變量,一個(gè)int變量就占四個(gè)字節(jié),所以說(shuō)位段在一定程度上節(jié)省了空間。
位段的內(nèi)存分配
1. 位段的成員可以是 int unsigned int signed int 或者是 char (屬于整形家族)類型
2. 位段的空間上是按照需要以4個(gè)字節(jié)( int )或者1個(gè)字節(jié)( char )的方式來(lái)開(kāi)辟的。
3. 位段涉及很多不確定因素,位段是不跨平臺(tái)的,注重可移植的程序應(yīng)該避免使用位段。
?二、什么是枚舉
性別有:男、女、保密,也可以一一列舉。
月份有12個(gè)月,也可以一一列舉
這里就可以使用枚舉了。
枚舉是要?jiǎng)?chuàng)造出一種新的類型,這種類型的取值是非常有限的,明確的只有那么幾種可能取值,我們就可以用枚舉來(lái)創(chuàng)造一個(gè)枚舉類型
枚舉類型的大小就是4.
1.枚舉類型的定義
#include<stdio.h>
//聲明枚舉類型
enum Color//enum枚舉關(guān)鍵字,Color枚舉類型,
{
RED,//大括號(hào)里面放的是枚舉的可能取值(常量)
GREEN,
BLUE
};
int main()
{
enum Color c = BLUE;
return 0;
}
大括號(hào)里面這些可能取值都是有值的,默認(rèn)從0開(kāi)始,一次遞增1,當(dāng)然在定義的時(shí)候也可以賦初值。
enum Color//顏色
{
RED=1,
GREEN=2,
BLUE=4
};
2.枚舉的優(yōu)點(diǎn)
我們可以使用 #define 定義常量,為什么非要使用枚舉?
枚舉的優(yōu)點(diǎn):
1. 增加代碼的可讀性和可維護(hù)性
2. 和#define定義的標(biāo)識(shí)符比較枚舉有類型檢查,更加嚴(yán)謹(jǐn)。
3. 防止了命名污染(封裝)
4. 便于調(diào)試
5. 使用方便,一次可以定義多個(gè)常量
三、聯(lián)合(共用體)
1.什么是聯(lián)合(共用體)
聯(lián)合也是一種特殊的自定義類型 這種類型定義的變量也包含一系列的成員,特征是這些成員公用同一塊空間(所以聯(lián)合也叫共用體)。
2.聯(lián)合(共用體)的定義
//聯(lián)合類型的聲明
union Un
{
char c;
int i;
};
//聯(lián)合變量的定義
union Un un;
//計(jì)算連個(gè)變量的大小
printf("%d\n", sizeof(un));
計(jì)算聯(lián)合(共用體)的大小

?這里為什么算出的結(jié)果是4呢,我們看下圖:


聯(lián)合的成員是共用同一塊內(nèi)存空間的,這樣一個(gè)聯(lián)合變量的大小,至少是最大成員的大?。ㄒ?yàn)槁?lián) 合至少得有能力保存最大的那個(gè)成員)。
3.聯(lián)合(共用體)的初始化
#include<stdio.h>
union Un
{
char c;
int i;
};
int main()
{
union Un u = { 10 };//初始化
u.i = 1000;//成員變量單獨(dú)初始化
u.c = 100;
printf("%p\n",&u );
printf("%p\n", &(u.c));
printf("%p\n", &(u.i));
return 0;
}

總結(jié)
這樣就簡(jiǎn)單介紹完了結(jié)構(gòu)體,枚舉和聯(lián)合體的定義,初始化,和簡(jiǎn)單的使用。寫(xiě)的比較潦草,如果上述文章有任何問(wèn)題?,歡迎大佬們提出質(zhì)疑,我會(huì)虛心學(xué)習(xí)和改正,最重要的是能共同進(jìn)步,共同成長(zhǎng),學(xué)習(xí)好編程。
到此這篇關(guān)于C語(yǔ)言自定義類型超詳細(xì)梳理之結(jié)構(gòu)體 枚舉 聯(lián)合體 的文章就介紹到這了,更多相關(guān)C語(yǔ)言自 結(jié)構(gòu)體 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
VS2019添加引用出錯(cuò):對(duì)COM組件的調(diào)用返回了錯(cuò)誤HRESULT E_FAIL(未能完成操作未指定的錯(cuò)誤)
這篇文章主要介紹了VS2019添加引用出錯(cuò):對(duì)COM組件的調(diào)用返回了錯(cuò)誤HRESULT E_FAIL(未能完成操作。未指定的錯(cuò)誤),需要的朋友可以參考下2020-07-07
Qt實(shí)現(xiàn)編寫(xiě)SMTP客戶端的示例詳解
這篇文章主要介紹了如何通過(guò)Qt實(shí)現(xiàn)編寫(xiě)SMTP客戶端,可以實(shí)現(xiàn)通過(guò)SMTP發(fā)送電子郵件(有文本,html,附件,內(nèi)聯(lián)文件等的MIME)。并支持SSL和SMTP身份驗(yàn)證,感興趣的可以學(xué)習(xí)一下2022-11-11
C語(yǔ)言實(shí)例問(wèn)題探究字符串函數(shù)的應(yīng)用
字符串函數(shù)(String processing function)也叫字符串處理函數(shù),指的是編程語(yǔ)言中用來(lái)進(jìn)行字符串處理的函數(shù),如C,pascal,Visual以及LotusScript中進(jìn)行字符串拷貝,計(jì)算長(zhǎng)度,字符查找等的函數(shù)2022-04-04
簡(jiǎn)要對(duì)比C語(yǔ)言中三個(gè)用于退出進(jìn)程的函數(shù)
這篇文章主要介紹了C語(yǔ)言中三個(gè)用于退出進(jìn)程的函數(shù)的對(duì)比,分別為_(kāi)exit()函數(shù)和on_exit()函數(shù)以及atexit()函數(shù),需要的朋友可以參考下2015-08-08
基于list循環(huán)刪除元素,迭代器失效的問(wèn)題詳解
下面小編就為大家?guī)?lái)一篇基于list循環(huán)刪除元素,迭代器失效的問(wèn)題詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12
c語(yǔ)言在控制臺(tái)判定鼠標(biāo)左鍵的小例子
c語(yǔ)言在控制臺(tái)判定鼠標(biāo)左鍵的小例子,需要的朋友可以參考一下2013-06-06
C++實(shí)現(xiàn)簡(jiǎn)單貪吃蛇小游戲
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-05-05
C語(yǔ)言二維數(shù)組應(yīng)用之井字棋游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言二維數(shù)組應(yīng)用之井字棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
Qt網(wǎng)絡(luò)編程實(shí)現(xiàn)TCP通信
這篇文章主要為大家詳細(xì)介紹了Qt網(wǎng)絡(luò)編程實(shí)現(xiàn)TCP通信,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08

