最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網 會員登陸 & 注冊

【零基礎學C語言】知識總結九:struct 結構體與 union 共用體

2022-10-12 18:09 作者:C語言編程__Plus  | 我要投稿



struct 結構體

struct即結構體,C程序中經常需要用相關的不同類型的數據來描述一個數據對象。例如,描述學生的綜合信息時,需要使用學生的學號、姓名、性別等不同類型的數據時,像這種數據類型總是在一起出現(xiàn),那么我們不如把這些變量裝入同一個“文件夾”中,這時用的關鍵字struct聲明的一種數據類型就是表示這個“文件夾”的使用。那么在說明和使用之前必須先定義它,也就是構造它。如同在說明和調用函數之前要先定義一樣。


結構體是一種集合,它里面包含了多個變量或數組,它們的類型可以相同,也可以不同,每個這樣的變量或數組都稱為結構體的成員,結構體也是一種數據類型,它由程序員自己定義,可以包含多個其他類型的數據,成員又稱為成員變量,它是結構體所包含的若干個基本的結構類型,必須用“{}”括起來,并且要以分號結束,每個成員應表明具體的數據類型,成員一般用名字訪問。結構體和數組類似,也是一組數據的集合,整體使用沒有太大的意義。數組使用下標[ ]獲訪問元素,結構體使用點號.訪問單個成員。通過這種方式可以獲取成員的值,也可以給成員賦值

數組:a[0]=10;? 結構體:today.day? (指針結構體用->訪問)結構體的成員可以包含其他結構體,也可以包含指向自己結構體類型的指針,而通常這種指針的應用是為了實現(xiàn)一些更高級的數據結構如鏈表和樹等。

聲明定義結構:

struct關鍵字+結構體的標志名+大括號里邊是成員+}后面的聲明此結構變量+末尾分號,一般有這些:

注意:

1、結構體本身并不會被作為數據而開辟內存,真正作為數據而在內存中存儲的是這種結構體所定義的變量。

2、先聲明結構體類型,再定義該類型的變量,聲明結構體類型,不分配空間定義結構體類型變量,就要分配內存空間

3、量使用占為少的類型,如,在可能的時候使用short代替int,按數據類型本身占用的位置從大到小排

4、除了可以對成員進行逐一賦值,也可以在定義時整體賦值:p1={struct week}{5,10}; 相當于 p1.x=5,p1.y=10;

p1=p2 表示 p1.x=p2.x ,? p1.y=p2.y; 不過整體賦值僅限于定義結構體變量的時候,在使用過程中只能對成員逐一賦值

5、結構體變量不能相加,相減,也不能相互乘除,但結構體可以相互賦值,也就是說,可以將一個結構體變量賦值給另一個結構體變量。但是前提是這兩個結構體變量的結構體類型必須相同

結構體的運算:要訪問整個結構,直接用結構變量的名字,對于整個結構,可以做賦值,取地址,也可以傳遞給函數參數


結構體數值

嵌套的結構體:

結構體相互引用:

一個結構體A中包含一個或多個與結構體B相關的成員, 且結構體B中也包含一個或多個與結構體A相關的成員稱為結構體的互引用.

但是要注意: 如果已經定義了兩個結構A和B ,在定義結構體A的成員b時,結構體B對A還未可見,故此時編譯器會報數據類型B未定義

解決的辦法是使用不完整聲明:


結構體函數與函數參數

結構體做函數形參:

整個結構可以作為參數的值傳入函數,這時候是在函數內新建一個結構變量,并復制調用者結構的值,也可以返回一個值,這和數組完全不同

用結構體變量作實參時,采取的也是“值傳遞”方式,將? 結構體變量所占的內存單元的內容(結構體變量成員列表)? 全部順序傳遞給形參,這里形參也得是結構體變量。

另一種做法

結構體做函數:

? 用結構體變量名作參數,這種傳遞方式是單向的,如果在執(zhí)行被調函數期間改變了形參(也是結構體變量)的值,該值不能返回主調函數,這往往造成使用上的不便,因此一般少用這種方法。

和本地變量一樣。在函數內部聲明的結構只能在函數內部使用,所以通常在函數外部聲明一個結構類型的,這樣就可以被多個函數所使用

結構體數組

結構體數組,是指數組中的每個元素都是一個結構體。在實際應用中,C語言結構體數組常被用來表示一個擁有相同數據結構的群體,比如一個班的學生、一個車間的職工等。結構體可以存儲不同的數據類型,將他們互相聯(lián)系起來。結構體數組可以連續(xù)存儲多個結構體,和數組作用相似。比如想定義同一個最小外接矩形的四個坐標值,并給予這個矩形一個特征編號。當需要存儲多個最小外接矩形的信息時,就需要動態(tài)申請一個結構體數組

定義結構體數組的方法很簡單,同定義結構體變量是一樣的,只不過將變量改成數組?;蛘哒f同前面介紹的普通數組的定義是一模一樣的:struct student? tp[10]; 這就定義了一個結構體數組,共有 10 個元素,每個元素都是一個結構體變量,都包含所有的結構體成員。

結構體數組的初始化與前面講的數值型數組的初始化也是一樣的,數值型數組初始化的方法和需要注意的問題在結構體數組的初始化中同樣適用,因為不管是數值型數組還是結構體數組都是數組。

結構體指針

和數組不同,結構變量的名字并不是結構變量的地址,必須使用&運算符? strcut node *tp=&nb;? 指針一般用->訪問結構體里邊的成員

指針變量非常靈活方便,可以指向任一類型的變量? ? ,若定義指針變量指向結構體類型變量,則可以通過指針來引用結構體類型變量。

這里說明:結構體和結構體變量是兩個不同的概念:結構體是一種數據類型,是一種創(chuàng)建變量的模板,編譯器不會為它分配內存空間,就像 int、float、char 這些關鍵字本身不占用內存一樣;結構體變量才包含實實在在的數據,才需要內存來存儲。所以用一個結構體去取一個結構體名的地址,這種寫法是錯誤的,也不能將它賦值給其他變量。

指向結構體數組的指針:

在之前講數值型數組的時候可以將數組名賦給一個指針變量,從而使該指針變量指向數組的首地址,然后用指針訪問數組的元素。結構體數組也是數組,所以同樣可以這么做。

我們知道,結構體數組的每一個元素都是一個結構體變量。如果定義一個結構體指針變量并把結構體數組的數組名賦給這個指針變量的話,就意味著將結構體數組的第一個元素,即第一個結構體變量的地址,也即第一個結構變量中的第一個成員的地址賦給了這個指針變量

typedef 別名

typedef是在編程語言中用來為復雜的聲明定義簡單的別名,新的名字是某種類型的別名,這樣做改善了程序的可讀性,它與宏定義有些差異。它本身是一種存儲類的關鍵字,與auto、extern、mutable、static、register等關鍵字不能出現(xiàn)在同一個表達式中。

typedef為C語言的關鍵字,功能是用來聲明一個已有的數據類型的新名字,比如 typedef int last ;? 這就使得last成為 int 類型的別名? 這樣last這個名字就可以代替int出現(xiàn)在變量定義和參數聲明的地方了

typedef也有一個特別的長處:它符合范圍規(guī)則,使用typedef定義的變量類型其作用范圍限制在所定義的函數或者文件內(取決于此變量定義的位置),而宏定義則沒有這種特性。

結構體的內存對齊方式(存儲空間)

結構體內存對齊:一個結構體變量定義完之后,其在內存中的存儲并不等于其所包含元素的寬度之和,元素是按照定義順序一個一個放到內存中去的,但并不是緊密排列的。從結構體存儲的首地址開始,每個元素放置到內存中時,它都會認為內存是按照自己的大小來劃分的,因此元素放置的位置一定會在自己寬度的整數倍上開始。

內存對齊可以大大提升內存訪問速度,是一種用空間換時間的方法。內存不對齊會導致每次讀取數據都會讀取兩次,使得內存讀取速度減慢。

cpu把內存當成是一塊一塊的,塊的大小可以是2,4,8,16 個字節(jié),因此CPU在讀取內存的時候是一塊一塊進行讀取的,塊的大小稱為內存讀取粒度。

如果結構體內存在長度大于處理器位數的元素,那么就以處理器的倍數為對齊單位;否則,如果結構體內的元素的長度都小于處理器的倍數的時候,便以結構體里面最長的數據元素為對齊單位。

另外? 結構體的內存地址就是它第一個成員變量的地址? isa永遠都是結構體中的第一個成員變量? 所以結構體的地址也就是其isa指針的地址

內存對齊簡介

由于內存的讀取時間遠遠小于CPU的存儲速度,這里用設定數據結構的對齊系數,即犧牲空間來換取時間的思想來提高CPU的存儲效率。

內存對齊”應該是編譯器的“管轄范圍”。編譯器為程序中的每個“數據單元”安排在適當的位置上。但是C語言的一個特點就是太靈活,太強大,它允許你干預“內存對齊”。如果你想了解更加底層的秘密,“內存對齊”對你就不應該再模糊了。這也是一個大小端模式的問題

每個特定平臺上的編譯器都有自己的默認“對齊系數”(也叫對齊模數)。程序員可以通過預編譯命令#pragma pack(n)來改變這一系數,其中的n就是你要指定的“對齊系數”。

規(guī)則:

1、數據成員對齊規(guī)則:結構(struct)(或聯(lián)合(union))的數據成員,第一個數據成員放在offset為0的地方,以后每個數據成員的對齊按照#pragma pack指定的數值和這個數據成員自身長度中,比較小的那個進行。

2、結構(或聯(lián)合)的整體對齊規(guī)則:在數據成員完成各自對齊之后,結構(或聯(lián)合)本身也要進行對齊,對齊將按照#pragma pack 指定的數值和結構(或聯(lián)合) 最大數據成員長度中,比較小的那個進行對齊。

3、結合1、2可推斷:當#pragma pack的n值等于或超過所有數據成員長度的時候,這個n值的大小將不產生任何效果。

#pragmapack(n)? 設定變量以n字節(jié)為對齊方式:

作用:指定結構體、聯(lián)合以及類成員

語法:#pragmapack( [show] | [push | pop] [, identifier], n )

1,pack提供數據聲明級別的控制,對定義不起作用;

2,調用pack時不指定參數,n將被設成默認值;

n:可選參數;指定packing的數值,以字節(jié)為單位;缺省數值是8,合法的數值分別是1、2、4、8、16。

其他參數都是可選的可先不了解

每個成員分別對齊,即每個成員按自己的方式對齊,并最小化長度;規(guī)則就是每個成員按其類型的對齊參數(通常是這個類型的大?。┖椭付▽R參數中較小的一個對齊。

大小端:

4、union 共用體(聯(lián)合體)

在進行某些算法的C語言編程的時候,需要使幾種不同類型的變量存放到同一段內存單元中。也就是使用覆蓋技術,幾個變量互相覆蓋。這種幾個不同的變量共同占用一段內存的結構,在C語言中 以關鍵字union聲明的一種數據結構,這種被稱作“共用體”類型結構,也叫聯(lián)合體。

? ? ? ? “聯(lián)合”與“結構”有一些相似之處。但兩者有本質上的不同。在結構中各成員有各自的內存空間,一個結構體變量的總長度大于等于各成員長度之和。而在“聯(lián)合”中,各成員共享一段內存空間,一個聯(lián)合變量的長度等于各成員中最長的長度。注意這里所謂的共享不是指把多個成員同時裝入一個聯(lián)合變量內,而是指該聯(lián)合變量可被賦予任一成員值,但每次只能賦一種值,賦入新值則沖去舊值,共用體變量中起作用的成員是最后一次存放的成員,在存入一個新成員后,原有成員就失去作用,共用體變量的地址和它的各成員的地址都是同一地址

一個聯(lián)合類型必須經過定義之后,才能把變量說明為該聯(lián)合類型:

注意:1、不能把共用體變量作為函數參數,也不能是函數帶回共用體變量,但可以使專用指向共用體變量的指針

2、所有成員占用同一段內存,修改一制個成員會影響其余所有成員。

共用體的訪問:

共用體訪問成員的值時一般使用.運算符,指針時用->運算符(和結構體是一樣的)

共用體的作用:

1、節(jié)省內存,有兩個很長的數據結構,不會同時使用,比如一個表示老師,一個表示學生,如果要統(tǒng)計教師和學生的情況用結構體的話就有點浪費了!用結構體的話,只占用最長的那個數據結構所占用的空間,就足夠了!

2、實現(xiàn)不同類型數據之間的類型轉換,遇到各種類型的數據共用存儲空間,很方便的實現(xiàn)了不同數據類型之間的轉換,不需要顯示的強制類型轉換。

其他:

1、確定CPU的模式:大端、小端模式確定

大小端不同,則存儲的方式也存在差別,比如int需要4個字節(jié),而char只需要1個字節(jié),根據1個字節(jié)所在的具體位置即可判定CPU的模式

2、寄存器的定義,實現(xiàn)整體的訪問和單項的訪問

希望對你有幫助!

作者:Mr_Li_

對啦對啦!另外的話為了幫助大家,輕松,高效學習C語言/C++,我給大家分享我收集的資源,從最零基礎開始的教程到C語言項目案例,幫助大家在學習C語言的道路上披荊斬棘!可以來我粉絲群領取哦~

微信公眾號:C語言編程學習基地

整理分享(多年學習的源碼、項目實戰(zhàn)視頻、項目筆記,基礎入門教程)最重要的是你可以在群里面交流提問編程問題哦!

【零基礎學C語言】知識總結九:struct 結構體與 union 共用體的評論 (共 條)

分享到微博請遵守國家法律
太白县| 泌阳县| 绵竹市| 邯郸市| 利辛县| 梅河口市| 普定县| 绥中县| 沈阳市| 库车县| 津南区| 肇庆市| 景德镇市| 利津县| 汝阳县| 呼和浩特市| 监利县| 吉水县| 阳新县| 吴江市| 喀喇沁旗| 南木林县| 定南县| 北流市| 溧水县| 金乡县| 石首市| 眉山市| 淮南市| 南阳市| 蓬莱市| 内乡县| 微山县| 临安市| 东海县| 特克斯县| 石楼县| 沐川县| 扶沟县| 三门县| 弋阳县|