C語言中的自定義類型:結構體珊肃、枚舉荣刑、聯(lián)合

我們知道c語言基本數(shù)據(jù)類型有:

本篇將重點介紹C語言中的自定義類型:結構體扣泊、枚舉、聯(lián)合

undefined結構體

定義:結構是一些值的集合嘶摊,這些值稱為成員變量。結構的每個成員可以是不同類型的變量评矩。

構造:

struct 結構體名

{

結構體所包含的變量或數(shù)組

};

聲明與定義

struct?Stu

{????char?name[20];//名字

????int?age;//年齡

????char?sex[5];//性別

????char?id[20];//學號}叶堆;int?main()

{????struct?Stu?s;????return?0;

}12345678910111213

代碼含義:

struct Stu是結構體類型,相當于int斥杜、float虱颗,不申請空間。Stu是結構體標簽蔗喂。

struct Stu s通過類型創(chuàng)建變量忘渔,申請空間(實例化)。

不完全聲明(匿名結構體類型)

#define?_CRT_SECURE_NO_WARNINGS?1#include?#include?struct{????int?a;????char?b;????float?c;

}x;struct{????int?a;????char?b;????float?c;

}*p;int?main()

{

????p?=?&x;

????system("pause");????return?0;

}123456789101112131415161718192021

上面的代碼執(zhí)行后發(fā)現(xiàn)是有bug的缰儿!?小編推薦一個學C語言/C++的學習裙【 六二七,零一二乖阵,四六四 】宣赔,無論你是大牛還是小白,是想轉(zhuǎn)行還是想入行都可以來了解一起進步一起學習瞪浸!裙內(nèi)有開發(fā)工具儒将,很多干貨和技術資料分享!

這是因為編輯器會把上面兩個聲明當成完全不同的兩個類型对蒲。

正確代碼:

struct?{????int?a;????char?b;????float?c;

}x,*p;int?main()

{

????p?=?&x;

????system("pause");????return?0;

}123456789101112

結構體的訪問

結構體變量訪問成員

結構變量的成員是通過定操作符(.)訪問的钩蚊。點操作符接受兩個操作數(shù)

struct?S?s;?

strcpy(s.name,?"zhangsan");//??使用.訪問name成員s.age?=?20;//使用.訪問age成員1234

結構體訪問指向變量的成員

有時候我們得到的不是一個結構體變量,而是指向一個結構體的指針蹈矮。

struct?S?

{????

????char?name[20];??

????int?age;??

}s;

void?print(struct?S*?ps)?

{????

????printf("name?=?%s???age?=?%d\n",?(*ps).name,?(*ps).age);?

????printf("name?=?%s???age?=?%d\n",?ps->name,?ps->age);????????????????

}12345678910

結構體的自引用

struct?Node?

{????

????int?data;????

????struct?Node*?next;?//指向同類型數(shù)據(jù)的指針};{{123456:0}}

結構體的不完整聲明

struct?B;?//不完整聲明struct?A?

{????

????int?_a;????

????struct?B*?pb;?

};?

struct?B?

{????

????int?_b;????

????struct?A*?pa;?

};123456789101112

結構體的內(nèi)存對齊

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

1.平臺原因(移植原因)

不是所有的硬件平臺都能訪問任意地址上的任意數(shù)據(jù)的砰逻;某些硬件平臺只能在某些地址處取某些特定的數(shù)據(jù),否則拋出硬件異常含滴。

2.性能原因

數(shù)據(jù)結構(尤其是棧)應該盡可能地在自然邊界上對齊诱渤。

原因在于,為了訪問未對齊的內(nèi)存谈况,處理器需要兩次內(nèi)存訪問勺美;而對其的內(nèi)存訪問僅需要一次訪問。

結構體對齊原則

1.第一個成員在與結構體變量偏移量為0 的地址處碑韵。

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

VS中默認的值是8祝闻,Linux中默認的值是4占卧。

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

4.如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數(shù)的整數(shù)倍處华蜒,結構體的整體大小就是所有最大對齊數(shù)(含嵌套結構體的對齊數(shù))的整數(shù)倍辙纬。

總的來說,結構體的內(nèi)存對齊是拿空間來換取時間的做法

struct?S1

{????char?c1;????int?i;????char?c2;

}printf("%s\n",sizeof(struct?S1));//1+3+4+1+3=12struct?S2?

{????

????char?c1;????

????int?i;?

};?

printf("%d\n",?sizeof(struct?S2));//1+1+2+4=8struct?S3?

{????

????double?d;????

????char?c;????int?i;?

};?

printf("%d\n",?sizeof(struct?S3));//8+1+3+4=16struct?S4?

{????

????char?c1;????struct?S3?s3;????double?d;

}printf("%d\n",?sizeof(struct?S4));//1+7+16+8=32123456789101112131415161718192021222324252627282930

結構體傳參

函數(shù)傳參的時候叭喜,參數(shù)是需要壓棧的贺拣。如果傳遞一個結構體對象的時候,結構體過大捂蕴,參數(shù)壓棧的系統(tǒng)開銷比較大譬涡,所以會導致性能的下降。所以啥辨,結構體傳參的時候涡匀,要傳結構體的地址。

struct?S

{

????char?c1;

????int?i;

????char?c2;

}

void?print(struct?S?*ps)

{????...}

int?main()

{

????print(&s);????return?0;

}12345678910111213141516

undefined位段

與結構體不同的是:

位段的成員必須是 int溉知、unsigned int陨瘩、int 或signed int 、char(屬于整型家族類型)

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

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

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

位段涉及很多不確定因素级乍,位段是不跨平臺的拾酝,注重可移植性的程序應該避免使用位段

struct??S?

{????

????char?_a:3;????

????char?_b:4;????

????char?_c:5;????

????char?_d:4;?

}struct?S?s={0};

s.a=10;

s.b=12;

s.c=3;

s.d=4;printf("%d\n",sizeeof(struct?S));//31234567891011121314

位段的跨平臺問題

int位段被當作有符號數(shù)還是無符號數(shù)無法確定

位段中最大位的數(shù)目不能確定(16位機器最大16,32位機器最大32)

位段中的成員在內(nèi)存中從左向右分配卡者,還是從右向左分配標準未定義蒿囤。

當一個結構包含兩個位段,第二個位段成員比較大崇决,無法容納于第一個位段剩余的位時材诽,時舍棄剩余的位還是利用,這是不確定的恒傻。

跟結構相比脸侥,位段可以達到同樣的效果,但是可以很好的節(jié)省空間盈厘,但是有跨平臺的問題存在

undefined枚舉

定義:顧名思義就是把可能的取值一一列舉

構造:

enum?枚舉名{

標識符[=整型常數(shù)],

標識符[=整型常數(shù)],...標識符[=整型常數(shù)]

}?枚舉變量;{{123456:0}}

如果枚舉沒有初始化, 即省掉”=整型常數(shù)”時, 則從第一個標識符開始, 順

次賦給標識符0, 1, 2, …睁枕。但當枚舉中的某個成員賦值后, 其后的成員按依次

加1的規(guī)則確定其值。

聲明與定義

enum?Color

{

????RED=1,

????GREEN=2;

????BLUE=4;

};enum?Color?clr?=?GREEN;{{1234567:0}}

enum Color是枚舉類型

{}中的內(nèi)容是枚舉類型的可能取值沸手,也叫枚舉常量外遇。這些可能取值都是有值的,默認從0開始契吉,一次遞增1跳仿,當然在定義的時候也可以賦初值。

注意:

枚舉中每個成員(標識符)結束符是”,”, 不是”;”, 最后一個成員可省略”,”捐晶。

初始化時可以賦負數(shù), 以后的標識符仍依次加1菲语。

枚舉變量只能取枚舉說明結構中的某個標識符常量妄辩。

枚舉優(yōu)點

增加代碼可讀性和可維護性

和#define定義的標識符比較,枚舉有類型檢查山上,更加嚴謹眼耀。

防止了命名污染(封裝)

便于調(diào)試

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

undefined聯(lián)合(共用體)

定義: 在進行某些算法的C語言編程的時候佩憾,需要使幾種不同類型的變量存放到同一段內(nèi)存單元中畔塔。這種幾個不同的變量共同占用一段內(nèi)存的結構,在C語言中鸯屿,被稱作”共用體”類型結構,簡稱共用體把敢。

構造:

union?共用體名{成員表列

}變量表列;1234

聲明與定義

我們用一段代碼說明寄摆,用結構體判斷編譯器的大小端(面試題)

int?check_sys()

{????union?Un

????{????????int?i;????????char?c;

????}un;

????un.i=1;????return?un.c?;

}int?main()

{????if(check_sys()==1)????????printf("小端\n");????else

????????printf("大端\n");????????return?01234567891011121314151617

聯(lián)合的特點

同一個內(nèi)存段可以用來存放幾種不同類型的成員,但是在每一瞬間只能存放其中的一種修赞,而不是同時存放幾種婶恼。換句話說,每一瞬間只有一個成員起作用柏副,其他的成員不起作用勾邦,即不是同時都在存在和起作用。

共用體變量中起作用的成員是最后一次存放的成員割择,在存入一個新成員后眷篇,原有成員就失去作用。

共用體變量的地址和它的各成員的地址都是同一地址荔泳。

不能對共用體變量名賦值蕉饼,也不能企圖引用變量名來得到一個值。

共用體類型可以出現(xiàn)在結構體類型的定義中玛歌,也可以定義共用體數(shù)組昧港。反之,結構體也可以出現(xiàn)在共用體類型的定義中支子,數(shù)組也可以作為共用體的成員创肥。

共用體變量也可以作為函數(shù)的參數(shù)和返回值

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

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

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

union?Un1?

{????

????char?c[5];????

????int?i;?

};?

union?Un2?

{????

????short?c[7];????

????int?i;?

};?

printf("%d\n",?sizeof(union?Un1));?//5*1+3=8printf("%d\n",?sizeof(union?Un2));//7*2+2=16123456789101112

undefined結構體和共同體的結合使用

我們網(wǎng)絡的IP地址是long類型的一段數(shù)字值朋,如: {{19237271:0}}叹侄,但是為了方便讀寫,我們寫成點分十進制形式:192.37.27.1

那么我們怎么轉(zhuǎn)換呢昨登?

union?ip_add

{????unsigned?long?addr;????struct?

????{????????unsigned?char?c1;????????unsigned?char?c2;?

????????unsigned?char?c3;????????unsigned?char?c4;

????}ip;

};int?main()

{????union?ip_addr?my_ip;

????my_ip.addr={{19237271:0}};????printf("%d.%d.%d.%d\n",my_ip.ip.c4,my_ip.ip.c3,my_ip.ip.c2,my_ip.ip.c1);????return?0;

}123456789101112131415161718

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末圈膏,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子篙骡,更是在濱河造成了極大的恐慌稽坤,老刑警劉巖丈甸,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異尿褪,居然都是意外死亡睦擂,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門杖玲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來顿仇,“玉大人,你說我怎么就攤上這事摆马【饰牛” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵囤采,是天一觀的道長述呐。 經(jīng)常有香客問我,道長蕉毯,這世上最難降的妖魔是什么乓搬? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮代虾,結果婚禮上进肯,老公的妹妹穿的比我還像新娘。我一直安慰自己棉磨,他們只是感情好江掩,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著乘瓤,像睡著了一般频敛。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上馅扣,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天斟赚,我揣著相機與錄音,去河邊找鬼差油。 笑死拗军,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的蓄喇。 我是一名探鬼主播发侵,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼妆偏!你這毒婦竟也來了刃鳄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤钱骂,失蹤者是張志新(化名)和其女友劉穎叔锐,沒想到半個月后挪鹏,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡愉烙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年讨盒,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片步责。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡返顺,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蔓肯,到底是詐尸還是另有隱情遂鹊,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布蔗包,位于F島的核電站秉扑,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏气忠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一赋咽、第九天 我趴在偏房一處隱蔽的房頂上張望旧噪。 院中可真熱鬧,春花似錦脓匿、人聲如沸淘钟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽米母。三九已至,卻和暖如春毡琉,著一層夾襖步出監(jiān)牢的瞬間铁瞒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工桅滋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留慧耍,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓丐谋,卻偏偏與公主長得像芍碧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子号俐,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內(nèi)容