摘要:一結(jié)構(gòu)體的聲明與定義結(jié)構(gòu)體的聲明結(jié)構(gòu)是一些值的集合,這些值稱為成員變量。但是結(jié)構(gòu)體變量的變量名并不是指向該結(jié)構(gòu)體的地址,所以要使用取地址運算符才能獲取其地址。因此,結(jié)構(gòu)體傳參的時候,要傳結(jié)構(gòu)體的地址。
C語言提供了不同的數(shù)據(jù)類型,比如說int、float、double、char等,不同的類型決定了一個變量在內(nèi)存中應該占據(jù)的空間以及表現(xiàn)形式。
但是,當我們定義一個人的時候,人的不同屬性就比較難用同一個數(shù)據(jù)類型來定義了,因為人的身高、年齡、體重等屬性往往需要不同數(shù)據(jù)類型,在這個時候,我們便引入結(jié)構(gòu)體這個概念。
結(jié)構(gòu)是一些值的集合,這些值稱為成員變量。結(jié)構(gòu)的每個成員可以是不同類型的變量
當我們面對的事物有多個不同的數(shù)據(jù)類型的時候,我們就可以使用結(jié)構(gòu)體來組織了。
比如說,一本書有書名、作者、售價、出版日期等等不同的數(shù)據(jù)類型,這時候我們可以創(chuàng)建結(jié)構(gòu)體來包含書的不同數(shù)據(jù)類型。
而結(jié)構(gòu)體聲明是描述結(jié)構(gòu)體組合的主要方法,語法格式為:
struct 結(jié)構(gòu)體名稱
{
結(jié)構(gòu)體成員1;
結(jié)構(gòu)體成員2;
結(jié)構(gòu)體成員3;
…
};//分號不能丟
【注意】
結(jié)構(gòu)體成員既可以是任何一種基本的數(shù)據(jù)類型,也可以是另一種結(jié)構(gòu)體,如果是后者就相當于結(jié)構(gòu)體的嵌套。(俗稱套娃)
例如:
struct Book//描述一本書的相關(guān)屬性,其中Book是這個框架的名稱{ char name[20];//書名 char author[20];//作者 float price;//價格};//分號一定不能丟
這樣就相當于描述了一本書的框架。
結(jié)構(gòu)成員的類型可以是標量、數(shù)組、指針、甚至是其他結(jié)構(gòu)體。
結(jié)構(gòu)體的聲明只是進行一個簡單的描述,實際上在沒有定義結(jié)構(gòu)體類型變量之前,它是不會在內(nèi)存中分配空間的。
也就是說,它還沒有被真正使用,虛擬存在,只有定義了結(jié)構(gòu)體類型變量,才真實存在。
舉個例子,上面定義了書的框架
struct Book//描述一本書的相關(guān)屬性,其中Book是這個框架的名稱{ char name[20];//書名 char author[20];//作者 float price;//價格};//分號一定不能丟
這里在編譯器中,并不會分配內(nèi)存空間,它僅僅是虛擬存在。而一旦我們定義了結(jié)構(gòu)體類型變量,它就可以被分配空間了。
比如:
struct Book//描述一本書的相關(guān)屬性,其中Book是這個框架的名稱{ char name[20];//書名 char author[20];//作者 float price;//價格};//分號一定不能丟int main(){ struct Book book;//局部變量--放在棧區(qū) return 0;}
我們在上面例子中也可以注意到,定義結(jié)構(gòu)體變量的語法是:
struct 結(jié)構(gòu)體名稱 結(jié)構(gòu)體變量名
此外,還可以在結(jié)構(gòu)體聲明的時候定義結(jié)構(gòu)體變量
struct Book//描述一本書的相關(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)體變量是一個全局變量,在其他函數(shù)中也可以對它進行訪問。
我們在定義一個變量或數(shù)組的時候可以對其進行初始化,
例如:
int a=10;int arr[10]={1,2,3,4,5,6,7,8,9,0};
同理,定義結(jié)構(gòu)體變量的時候,我們也可以同時為其初始化
struct Book//描述一本書的相關(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)體變量初始化了,也就是定義變量的同時賦初值 return 0;}
結(jié)構(gòu)體變量訪問成員 結(jié)構(gòu)變量的成員是通過點操作符(.)訪問的。點操作符接受兩個操作數(shù)。
比如,book.name就是引用book結(jié)構(gòu)體變量的name成員,它是一個字符數(shù)組。
#include struct Book//描述一本書的相關(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)體變量初始化了,也就是定義變量的同時賦初值 printf("%s %s %f/n", book.name, book.author, book.price);//用. 來訪問 return 0;}
如果訪問嵌套的結(jié)構(gòu)體成員的話,就需要使用多層點號運算符來進行操作。因為C語言的結(jié)構(gòu)體只能對最底層的成員進行訪問,如果存在多級結(jié)構(gòu)體嵌套的話,就需要一級一級地深入,直到找到最底層的成員才行
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);//使用了兩層點號運算符尋找成員 return 0;}
在開頭的時候說過,結(jié)構(gòu)的成員可以是標量、數(shù)組、指針。
在這里,我們來認識一下結(jié)構(gòu)體指針。
struct Book *pt;
這里聲明了一個指向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ù)組名指向的是第一個元素的地址,所以可以直接將數(shù)組名賦值給指針變量。但是結(jié)構(gòu)體變量的變量名并不是指向該結(jié)構(gòu)體的地址,所以要使用取地址運算符(&)才能獲取其地址。
如上面的:
struct T*pt = &t;//拿到地址的方式
通過上面的例子我們也可以發(fā)現(xiàn),通過結(jié)構(gòu)體指針訪問結(jié)構(gòu)體成員有以下兩種方法:
(1)(*結(jié)構(gòu)體指針).成員名
(2)結(jié)構(gòu)體指針->成員名
第一種由于點號運算符(.)比指針的取值運算符(*)優(yōu)先級高,所以要使用小口號先對指針進行解引用,讓它變成該結(jié)構(gòu)體變量,再用點運算符取訪問其成員。
以上兩種方法在實現(xiàn)的時候完全等價。但是,切記,點號(.)只能用于結(jié)構(gòu)體,而箭頭(->)只能用于結(jié)構(gòu)體指針。
【打印結(jié)果一樣】
當二者皆可用的時候,優(yōu)先采用第二種方法,因為箭頭具有指向性,很直觀的就可以把它與指針聯(lián)系起來了。
函數(shù)調(diào)用的時候,參數(shù)的傳遞就是值傳遞的過程,也就是將實參傳給形參的過程。所以,結(jié)構(gòu)體變量可以作為函數(shù)的參數(shù)傳遞,兩個相同結(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ù)傳遞過去了。
那么,上面的 print1 和 print2 函數(shù)哪個好些?
答案是:首選print2函數(shù)。 原因:
函數(shù)傳參的時候,參數(shù)是需要壓棧的。 如果傳遞一個結(jié)構(gòu)體對象的時候,結(jié)構(gòu)體過大,參數(shù)壓棧的的系統(tǒng)開銷比較大,所以會導致性能的下降。
因此,結(jié)構(gòu)體傳參的時候,要傳結(jié)構(gòu)體的地址。
希望能對看到的大家有所幫助!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/121141.html
摘要:為了減少在中創(chuàng)建的字符串的數(shù)量,字符串類維護了一個字符串常量池。但是當執(zhí)行了方法后,將指向字符串常量池中的那個字符串常量。由于和都是字符串常量池中的字面量的引用,所以。究其原因,是因為常量池要保存的是已確定的字面量值。 String,是Java中除了基本數(shù)據(jù)類型以外,最為重要的一個類型了。很多人會認為他比較簡單。但是和String有關(guān)的面試題有很多,下面我隨便找兩道面試題,看看你能不能...
摘要:結(jié)構(gòu)體類型的特殊聲明在初階結(jié)構(gòu)體中,我們已經(jīng)將了結(jié)構(gòu)體類型是如何進行聲明的,那么在這里,我們將講一些特殊的結(jié)構(gòu)體聲明不完全的聲明。所以我們應該這樣寫通過指針來找到下一個同類型結(jié)構(gòu)體的寫法,我們就稱之為結(jié)構(gòu)體的自引用。 ...
摘要:摘要本文主要介紹了亞馬遜的使用過程中發(fā)現(xiàn)的問題以及基于亞馬遜實例自己搭建服務器的一些經(jīng)驗。之前公司使用亞馬遜的實例,一切都非常好。但是我們架設在亞馬遜實例上的服務器為了安全起見都是跨網(wǎng)段的,不支持,實現(xiàn)不了啊。 摘要 本文主要介紹了亞馬遜RDS的使用過程中發(fā)現(xiàn)的問題以及基于亞馬遜EC2實例自己搭建Mysql服務器的一些經(jīng)驗。 showImg(https://segmentfault.c...
閱讀 1321·2023-04-26 03:05
閱讀 778·2021-10-19 11:43
閱讀 3227·2021-09-26 09:55
閱讀 835·2019-08-30 15:56
閱讀 991·2019-08-30 15:44
閱讀 1246·2019-08-30 15:44
閱讀 2726·2019-08-30 14:23
閱讀 3244·2019-08-30 13:13