C語(yǔ)言結(jié)構(gòu)體的全方面解讀
前言
C語(yǔ)言提供了不同的數(shù)據(jù)類型,比如說(shuō)int、float、double、char等,不同的類型決定了一個(gè)變量在內(nèi)存中應(yīng)該占據(jù)的空間以及表現(xiàn)形式。
但是,當(dāng)我們定義一個(gè)人的時(shí)候,人的不同屬性就比較難用同一個(gè)數(shù)據(jù)類型來(lái)定義了,因?yàn)槿说纳砀?、年齡、體重等屬性往往需要不同數(shù)據(jù)類型,在這個(gè)時(shí)候,我們便引入結(jié)構(gòu)體這個(gè)概念。
一、結(jié)構(gòu)體的聲明與定義
1.結(jié)構(gòu)體的聲明
結(jié)構(gòu)是一些值的集合,這些值稱為成員變量。結(jié)構(gòu)的每個(gè)成員可以是不同類型的變量
當(dāng)我們面對(duì)的事物有多個(gè)不同的數(shù)據(jù)類型的時(shí)候,我們就可以使用結(jié)構(gòu)體來(lái)組織了。
比如說(shuō),一本書(shū)有書(shū)名、作者、售價(jià)、出版日期等等不同的數(shù)據(jù)類型,這時(shí)候我們可以創(chuàng)建結(jié)構(gòu)體來(lái)包含書(shū)的不同數(shù)據(jù)類型。
而結(jié)構(gòu)體聲明是描述結(jié)構(gòu)體組合的主要方法,語(yǔ)法格式為:
struct 結(jié)構(gòu)體名稱
{
結(jié)構(gòu)體成員1;
結(jié)構(gòu)體成員2;
結(jié)構(gòu)體成員3;
…
};//分號(hào)不能丟
【注意】
結(jié)構(gòu)體成員既可以是任何一種基本的數(shù)據(jù)類型,也可以是另一種結(jié)構(gòu)體,如果是后者就相當(dāng)于結(jié)構(gòu)體的嵌套。(俗稱套娃)
例如:
struct Book//描述一本書(shū)的相關(guān)屬性,其中Book是這個(gè)框架的名稱 { char name[20];//書(shū)名 char author[20];//作者 float price;//價(jià)格 };//分號(hào)一定不能丟
這樣就相當(dāng)于描述了一本書(shū)的框架。
2.結(jié)構(gòu)成員的類型
結(jié)構(gòu)成員的類型可以是標(biāo)量、數(shù)組、指針、甚至是其他結(jié)構(gòu)體。
3.結(jié)構(gòu)體的定義
結(jié)構(gòu)體的聲明只是進(jìn)行一個(gè)簡(jiǎn)單的描述,實(shí)際上在沒(méi)有定義結(jié)構(gòu)體類型變量之前,它是不會(huì)在內(nèi)存中分配空間的。
也就是說(shuō),它還沒(méi)有被真正使用,虛擬存在,只有定義了結(jié)構(gòu)體類型變量,才真實(shí)存在。
舉個(gè)例子,上面定義了書(shū)的框架
struct Book//描述一本書(shū)的相關(guān)屬性,其中Book是這個(gè)框架的名稱 { char name[20];//書(shū)名 char author[20];//作者 float price;//價(jià)格 };//分號(hào)一定不能丟
這里在編譯器中,并不會(huì)分配內(nèi)存空間,它僅僅是虛擬存在。而一旦我們定義了結(jié)構(gòu)體類型變量,它就可以被分配空間了。
比如:
struct Book//描述一本書(shū)的相關(guān)屬性,其中Book是這個(gè)框架的名稱 { char name[20];//書(shū)名 char author[20];//作者 float price;//價(jià)格 };//分號(hào)一定不能丟 int main() { struct Book book;//局部變量--放在棧區(qū) return 0; }
我們?cè)谏厦胬又幸部梢宰⒁獾?,定義結(jié)構(gòu)體變量的語(yǔ)法是:
struct 結(jié)構(gòu)體名稱 結(jié)構(gòu)體變量名
此外,還可以在結(jié)構(gòu)體聲明的時(shí)候定義結(jié)構(gòu)體變量
struct Book//描述一本書(shū)的相關(guān)屬性 { char name[20]; char author[20]; float price; }b1,b2;//b1,b2是全局變量。放在靜態(tài)區(qū) int main() { struct Book book;//局部變量--放在棧區(qū) return 0; }
b1、b2結(jié)構(gòu)體變量是一個(gè)全局變量,在其他函數(shù)中也可以對(duì)它進(jìn)行訪問(wèn)。
二、初始化結(jié)構(gòu)體
我們?cè)诙x一個(gè)變量或數(shù)組的時(shí)候可以對(duì)其進(jìn)行初始化,
例如:
int a=10; int arr[10]={1,2,3,4,5,6,7,8,9,0};
同理,定義結(jié)構(gòu)體變量的時(shí)候,我們也可以同時(shí)為其初始化
struct Book//描述一本書(shū)的相關(guān)屬性 { char name[20]; char author[20]; float price; }b1,b2;//b1,b2是全局變量。放在靜態(tài)區(qū) int main() { struct Book book= { "《笑傲江湖》","金庸",30 };//這樣的話,就將結(jié)構(gòu)體變量初始化了,也就是定義變量的同時(shí)賦初值 return 0; }
三、訪問(wèn)結(jié)構(gòu)體成員
結(jié)構(gòu)體變量訪問(wèn)成員 結(jié)構(gòu)變量的成員是通過(guò)點(diǎn)操作符(.)訪問(wèn)的。點(diǎn)操作符接受兩個(gè)操作數(shù)。
比如,book.name就是引用book結(jié)構(gòu)體變量的name成員,它是一個(gè)字符數(shù)組。
#include <stdio.h> struct Book//描述一本書(shū)的相關(guān)屬性 { char name[20]; char author[20]; float price; }b1, b2;//b1,b2是全局變量。放在靜態(tài)區(qū) int main() { struct Book book= { "《笑傲江湖》", "金庸", 30 };//這樣的話,就將結(jié)構(gòu)體變量初始化了,也就是定義變量的同時(shí)賦初值 printf("%s %s %f\n", book.name, book.author, book.price); //用. 來(lái)訪問(wèn) return 0; }
四、結(jié)構(gòu)體嵌套
如果訪問(wèn)嵌套的結(jié)構(gòu)體成員的話,就需要使用多層點(diǎn)號(hào)運(yùn)算符來(lái)進(jìn)行操作。因?yàn)镃語(yǔ)言的結(jié)構(gòu)體只能對(duì)最底層的成員進(jìn)行訪問(wèn),如果存在多級(jí)結(jié)構(gòu)體嵌套的話,就需要一級(jí)一級(jí)地深入,直到找到最底層的成員才行
struct S { int a; char c; double d; }; struct T { struct S s;//結(jié)構(gòu)體嵌套 char name[20]; int num; }; int main() { struct T t = { {100,'c',3.14},"里斯",30 }; printf("%d %c %f %s %d\n", t.s.a, t.s.c, t.s.d, t.name, t.num);//使用了兩層點(diǎn)號(hào)運(yùn)算符尋找成員 return 0; }
五、結(jié)構(gòu)體指針
在開(kāi)頭的時(shí)候說(shuō)過(guò),結(jié)構(gòu)的成員可以是標(biāo)量、數(shù)組、指針。
在這里,我們來(lái)認(rèn)識(shí)一下結(jié)構(gòu)體指針。
struct Book *pt;
這里聲明了一個(gè)指向Book結(jié)構(gòu)體類型的指針變量pt
struct S { int a; char c; double d; }; struct T { struct S s; char name[20]; int num; }; int main() { struct T t = { {100,'c',3.14},"里斯",30 }; printf("%d %c %f %s %d\n", t.s.a, t.s.c, t.s.d, t.name, t.num); struct T*pt = &t;//拿到地址的方式 printf("%d %c %f %s %d\n", (*pt).s.a, (*pt).s.c, (*pt).s.d, (*pt).name, (*pt).num); printf("%d %c %f %s %d\n",pt->s.a,pt->s.c,pt->s.d,pt->name,pt->num); return 0; }
【注意】數(shù)組名指向的是第一個(gè)元素的地址,所以可以直接將數(shù)組名賦值給指針變量。但是結(jié)構(gòu)體變量的變量名并不是指向該結(jié)構(gòu)體的地址,所以要使用取地址運(yùn)算符(&)才能獲取其地址。
如上面的:
struct T*pt = &t;//拿到地址的方式
通過(guò)上面的例子我們也可以發(fā)現(xiàn),通過(guò)結(jié)構(gòu)體指針訪問(wèn)結(jié)構(gòu)體成員有以下兩種方法:
(1)(*結(jié)構(gòu)體指針).成員名
(2)結(jié)構(gòu)體指針->成員名
第一種由于點(diǎn)號(hào)運(yùn)算符(.)比指針的取值運(yùn)算符(*)優(yōu)先級(jí)高,所以要使用小口號(hào)先對(duì)指針進(jìn)行解引用,讓它變成該結(jié)構(gòu)體變量,再用點(diǎn)運(yùn)算符取訪問(wèn)其成員。
以上兩種方法在實(shí)現(xiàn)的時(shí)候完全等價(jià)。但是,切記,點(diǎn)號(hào)(.)只能用于結(jié)構(gòu)體,而箭頭(->)只能用于結(jié)構(gòu)體指針。
【打印結(jié)果一樣】
當(dāng)二者皆可用的時(shí)候,優(yōu)先采用第二種方法,因?yàn)榧^具有指向性,很直觀的就可以把它與指針聯(lián)系起來(lái)了。
六、結(jié)構(gòu)體傳參
函數(shù)調(diào)用的時(shí)候,參數(shù)的傳遞就是值傳遞的過(guò)程,也就是將實(shí)參傳給形參的過(guò)程。所以,結(jié)構(gòu)體變量可以作為函數(shù)的參數(shù)傳遞,兩個(gè)相同結(jié)構(gòu)體類型的結(jié)構(gòu)體變量也支持直接賦值。
struct S { int arr[100]; int num; char ch; double d; }; //結(jié)構(gòu)體傳參 void print1(struct S ss) { printf("%d %d %d %c %1f", ss.arr[0],ss.arr[2],ss.num,ss.ch,ss.d); } //結(jié)構(gòu)體地址傳參 void print2(struct S*ps) { printf("%d %d %d %c %1f", ps->arr[0], ps->arr[2], ps->num, ps->ch, ps->d); } int main() { struct S s = { {1,2,3,4,5}, 100, 'w',3.14 }; print1(s);//傳結(jié)構(gòu)體 print2(&s);//傳地址 return 0; }
可以看到,確實(shí)把參數(shù)傳遞過(guò)去了。
那么,上面的 print1 和 print2 函數(shù)哪個(gè)好些?
答案是:首選print2函數(shù)。 原因:
函數(shù)傳參的時(shí)候,參數(shù)是需要壓棧的。 如果傳遞一個(gè)結(jié)構(gòu)體對(duì)象的時(shí)候,結(jié)構(gòu)體過(guò)大,參數(shù)壓棧的的系統(tǒng)開(kāi)銷比較大,所以會(huì)導(dǎo)致性能的下降。
因此,結(jié)構(gòu)體傳參的時(shí)候,要傳結(jié)構(gòu)體的地址。
總結(jié)
本文介紹的是C語(yǔ)言結(jié)構(gòu)體的一些基礎(chǔ)知識(shí),結(jié)構(gòu)體的內(nèi)容還遠(yuǎn)遠(yuǎn)不止這些,在以后學(xué)習(xí)到了更深的內(nèi)容之后,或許會(huì)再寫(xiě)一篇博客深入介紹。此外,本文參考了小甲魚(yú)的《零基礎(chǔ)入門(mén)學(xué)習(xí)C語(yǔ)言》一書(shū),以及網(wǎng)上的部分資料,與自己在學(xué)習(xí)聽(tīng)課時(shí)的筆記,梳理而成。其中或有遺漏之處,或內(nèi)容的來(lái)源,或講解的疏漏,還請(qǐng)看到的大家多多包含與見(jiàn)諒!
希望能對(duì)看到的大家有所幫助!
到此這篇關(guān)于C語(yǔ)言結(jié)構(gòu)體的全方面解讀的文章就介紹到這了,更多相關(guān)C語(yǔ)言 結(jié)構(gòu)體內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言如何利用輾轉(zhuǎn)相除法求最大公約數(shù)
這篇文章主要介紹了C語(yǔ)言如何利用輾轉(zhuǎn)相除法求最大公約數(shù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08C++多態(tài)的實(shí)現(xiàn)機(jī)制深入理解
這篇文章主要介紹了C++多態(tài)的實(shí)現(xiàn)機(jī)制理解的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07C++簡(jiǎn)單實(shí)現(xiàn)Dijkstra算法
這篇文章主要為大家詳細(xì)介紹了C++簡(jiǎn)單實(shí)現(xiàn)Dijkstra算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05

C++實(shí)現(xiàn)在文本中找出某個(gè)單詞的位置信息

C++算法計(jì)時(shí)器的實(shí)現(xiàn)示例

關(guān)于STL的erase()陷阱-迭代器失效問(wèn)題的總結(jié)

C語(yǔ)言實(shí)現(xiàn)C++繼承和多態(tài)的代碼分享