最全嵌入式C語言結(jié)構(gòu)體知識點_第1頁
最全嵌入式C語言結(jié)構(gòu)體知識點_第2頁
最全嵌入式C語言結(jié)構(gòu)體知識點_第3頁
最全嵌入式C語言結(jié)構(gòu)體知識點_第4頁
最全嵌入式C語言結(jié)構(gòu)體知識點_第5頁
已閱讀5頁,還剩4頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

Word最全嵌入式C語言結(jié)構(gòu)體知識點結(jié)構(gòu)體的定義

結(jié)構(gòu)體(struct)是由一系列具有相同類型或不同類型的數(shù)據(jù)構(gòu)成的數(shù)據(jù)集合,也叫結(jié)構(gòu)。

結(jié)構(gòu)體和其他類型基礎(chǔ)數(shù)據(jù)類型一樣,例如int類型,char類型;只不過結(jié)構(gòu)體可以做成你想要的數(shù)據(jù)類型,以方便日后的使用。

在實際項目中,結(jié)構(gòu)體是大量存在的。研發(fā)人員常使用結(jié)構(gòu)體來封裝一些屬性來組成新的類型。由于(C語言)無法操作數(shù)據(jù)庫,所以在項目中通過對結(jié)構(gòu)體內(nèi)部變量的操作將大量的數(shù)據(jù)存儲在內(nèi)存中,以完成對數(shù)據(jù)的存儲和操作。

在實際問題中有時候我們需要幾種數(shù)據(jù)類型一起來修飾某個變量。

例如一個學(xué)生的信息就需要學(xué)號(字符串),姓名(字符串),年齡(整型)等等。

這些數(shù)據(jù)類型都不同但是他們又是表示一個整體,要存在聯(lián)系,那么我們就需要一個新的數(shù)據(jù)類型——結(jié)構(gòu)體,它就將不同類型的數(shù)據(jù)存放在一起,作為一個整體進行處理。

結(jié)構(gòu)體在函數(shù)中的作用不是簡便,其最主要的作用就是封裝。封裝的好處就是可以再次利用。讓使用者不必關(guān)心這個是什么,只要根據(jù)定義使用就可以了。

結(jié)構(gòu)體的大小不是結(jié)構(gòu)體元素單純相加就行的,因為我們現(xiàn)在主流的計算機使用的都是32Bit字長的(CPU),對這類型的CPU取4個字節(jié)的數(shù)要比取一個字節(jié)要高效,也更方便。所以在結(jié)構(gòu)體中每個成員的首地址都是4的整數(shù)倍的話,取數(shù)據(jù)元素時就會相對更高效,這就是內(nèi)存對齊的由來。

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

規(guī)則

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

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

3、結(jié)合1、2可推斷:當#pragmapack的n值等于或超過所有數(shù)據(jù)成員長度的時候,這個n值的大小將不產(chǎn)生任何效果。

在C語言中,可以定義結(jié)構(gòu)體類型,將多個相關(guān)的變量包裝成為一個整體使用。在結(jié)構(gòu)體中的變量,可以是相同、部分相同,或完全不同的數(shù)據(jù)類型。結(jié)構(gòu)體不能包含函數(shù)。

在面向?qū)ο蟮某绦蛟O(shè)計中,對象具有狀態(tài)(屬性)和行為,狀態(tài)保存在成員變量中,行為通過成員方法(函數(shù))來實現(xiàn)。C語言中的結(jié)構(gòu)體只能描述一個對象的狀態(tài),不能描述一個對象的行為。

在(C++)中,考慮到C語言到C++語言過渡的連續(xù)性,對結(jié)構(gòu)體進行了擴展,C++的結(jié)構(gòu)體可以包含函數(shù),這樣,C++的結(jié)構(gòu)體也具有類的功能,與class不同的是,結(jié)構(gòu)體包含的函數(shù)默認為public,而不是private。結(jié)構(gòu)體聲明下面介紹一下上面的結(jié)構(gòu)體聲明;1、首先使用關(guān)鍵字struct,它表示接下來是一個結(jié)構(gòu)體。2、后面是一個可選的標志(book),它是用來引用該結(jié)構(gòu)體的快速標記。

因此我們以后就可以這樣創(chuàng)建數(shù)據(jù)對象structbooklibrary;//把library設(shè)為一個可以使用book結(jié)構(gòu)體的結(jié)構(gòu)體變量,則library這個變量就包含了其book結(jié)構(gòu)體中的所有元素3、接下來就是一個花括號,括起了結(jié)構(gòu)體成員列表,及每個成員變量,使用的都是其自己的聲明方式來描述,用分號來結(jié)束描述;例如:chartitle[MAXTITL];字符數(shù)組就是這樣聲明的,用分號結(jié)束;注意:其中每個成員可以使用任何一種C數(shù)據(jù)結(jié)構(gòu)甚至是其他的結(jié)構(gòu)體,也是可以的;4、在結(jié)束花括號后的分號表示結(jié)構(gòu)體設(shè)計定義的結(jié)束。關(guān)于其struct聲明的位置,也就是這段代碼要放到哪里。同樣這也是具有作用域的。這種聲明如果放在任何函數(shù)的外面,那么則標記可以在在本文件中,該聲明后面的所有函數(shù)都可以使用。如果這種聲明在某個函數(shù)的內(nèi)部,則它的標記只能在內(nèi)部使用,并且在其聲明之后;關(guān)于我們不斷說的,標記名是可選的,那么我們什么時候可以省略,什么時候一定不能省略呢?如果是上面那種聲明定義的方法,并且想在一個地方定義結(jié)構(gòu)體設(shè)計,而在其他地方定義實際的結(jié)構(gòu)體變量,那么就必須使用標記;可以省略,設(shè)計的同時就創(chuàng)建該結(jié)構(gòu)體變量,但是這種設(shè)計是一次性的。一般格式就是:struct結(jié)構(gòu)體名(也就是可選標記名){

成員變量;};//使用分號表示定義結(jié)束。C語言結(jié)構(gòu)體定義的三種方式1、最標準的方式:

2、不環(huán)保的方式

3、最奈何人的方式

定義結(jié)構(gòu)體變量

之前我們結(jié)構(gòu)體類型的定義(結(jié)構(gòu)體的聲明)只是告訴編譯器該如何表示數(shù)據(jù),但是它沒有讓計算機為其分配空間。

我們要使用結(jié)構(gòu)體,那么就需要創(chuàng)建變量,也就是結(jié)構(gòu)體變量;

創(chuàng)建一個結(jié)構(gòu)體變量;分析:

structbook的作用:在結(jié)構(gòu)體聲明中,structbook所起到的作用就像int等基礎(chǔ)數(shù)據(jù)類型名作用一樣。其一:其二,用typedef定義新類型名來代替已有類型名,即給已有類型重新命名;一般格式為;typedef已有類型新類型名;總結(jié)一下關(guān)于結(jié)構(gòu)體變量的定義:1、先定義結(jié)構(gòu)體類型后再定義結(jié)構(gòu)體變量;

格式為:struct結(jié)構(gòu)體名變量名列表;

2、在定義結(jié)構(gòu)體類型的同時定義結(jié)構(gòu)體變量;

格式為:直接定義結(jié)構(gòu)體類型變量,就是第二種中省略結(jié)構(gòu)體名的情況;

這種方式不能指明結(jié)構(gòu)體類型名而是直接定義結(jié)構(gòu)體變量,并且在只定義一次結(jié)構(gòu)體變量時適用,無結(jié)構(gòu)體名的結(jié)構(gòu)體類型是無法重復(fù)使用的。

也就是說,后面程序不能再定義此類型變量了,除非再寫一次重復(fù)的struct。對于結(jié)構(gòu)體變量的初始化先回憶一下關(guān)于基本數(shù)據(jù)類型和數(shù)組類型的初始化:再回到結(jié)構(gòu)體變量的初始化吧

關(guān)于結(jié)構(gòu)體變量的初始化與初始化數(shù)組類似;

也是使用花括號括起來,用逗號分隔的初始化好項目列表。注意,每個初始化項目必須要和要初始化的結(jié)構(gòu)體成員類型相匹配。對于結(jié)構(gòu)體的指定初始化:

訪問結(jié)構(gòu)體成員結(jié)構(gòu)體就像一個超級數(shù)組,在這個超級數(shù)組內(nèi),一個元素可以是char類型,下個元素就可以是flaot類型,再下個還可以是int數(shù)組型,這些都是存在的。

在數(shù)組里面我們通過下標可以訪問一個數(shù)組的各個元素,那么如何訪問結(jié)構(gòu)體中的各個成員呢?

用結(jié)構(gòu)成員運算符點(.)就可以了;

結(jié)構(gòu)體變量名.成員名;

注意,點其結(jié)合性是自左至右的,它在所有的運算符中優(yōu)先級是最高的;

例如,s1.title指的就是s1的title部分;s1.author指的就是s1的author部分;s1.value指的就是s1的value部分。

然后就可以像字符數(shù)組那樣使用s1.title,像使用float數(shù)據(jù)類型一樣使用s1.value;

注意,s1雖然是個結(jié)構(gòu)體,但是s1.value卻是float型的。

因此s1.value就相當于float類型的變量名一樣,按照float類型來使用;

例如:printf(“%s%s%f”,s1.title,s1.author,s1.value);//訪問結(jié)構(gòu)體變量元素注意s(can)f(“%d”,這語句存在兩個運算符,">如果其成員本身又是一種結(jié)構(gòu)體類型,那么可以通過若干個成員運算符,一級一級的找到最低一級成員再對其進行操作;

結(jié)構(gòu)體變量名.成員.子成員………最低一級子成員;

整體與分開

可以將一個結(jié)構(gòu)體變量作為一個整體賦值給另一相同類型的結(jié)構(gòu)體變量,可以到達整體賦值的效果;這個成員變量的值都將全部整體賦值給另外一個變量;

不能將一個結(jié)構(gòu)體變量作為一個整體進行輸入和輸出;在輸入輸出結(jié)構(gòu)體數(shù)據(jù)時,必須分別指明結(jié)構(gòu)體變量的各成員;

結(jié)構(gòu)體長度數(shù)據(jù)類型的字節(jié)數(shù):16位編譯器char:1個字節(jié)

char*(即指針變量):

2個字節(jié)

short

int

:

2個字節(jié)

int:

2個字節(jié)

unsigned

int

:

2個字節(jié)

float:

4個字節(jié)

double:

8個字節(jié)

long:

4個字節(jié)

long

long:

8個字節(jié)

unsigned

long:

4個字節(jié)char:1個字節(jié)

char*(即指針變量):

4個字節(jié)(32位的尋址空間是2^32,即32個bit,也就是4個字節(jié)。同理64位編譯器)

short

int

:

2個字節(jié)

int:

4個字節(jié)

unsigned

int

:

4個字節(jié)

float:

4個字節(jié)

double:

8個字節(jié)

long:

4個字節(jié)long

long:

8個字節(jié)

unsigned

long:

4個字節(jié)那么,下面這個結(jié)構(gòu)體類型占幾個字節(jié)呢?結(jié)構(gòu)體字節(jié)對齊

通過下面的方式,可以清楚知道為什么是8字節(jié)。1、定義20個char元素的數(shù)組2、定義結(jié)構(gòu)體類型的指針ps指向ss數(shù)組3、打印輸出各個成員結(jié)構(gòu)體嵌套

結(jié)構(gòu)體嵌套結(jié)構(gòu)體方式:占用內(nèi)存空間struct結(jié)構(gòu)體,在結(jié)構(gòu)體定義的時候不能申請內(nèi)存空間,不過如果是結(jié)構(gòu)體變量,聲明的時候就可以分配——兩者關(guān)系就像C++的類與對象,對象才分配內(nèi)存(不過嚴格講,作為代碼段,結(jié)構(gòu)體定義部分“.(te)xt”真的就不占空間了么?當然,這是另外一個范疇的(話題))。結(jié)構(gòu)體的大小通常(只是通常)是結(jié)構(gòu)體所含變量大小的總和,下面打印輸出上述結(jié)構(gòu)體的size:下邊說說不通常的情況對于結(jié)構(gòu)體中比較小的成員,可能會被強行對齊,造成空間的空置,這和讀取內(nèi)存的機制有關(guān)。為了效率,通常32位機按4字節(jié)對齊,小于的都當4字節(jié),有連續(xù)小于4字節(jié)的,可以不著急對齊,等到湊夠了整,加上下一個元素超出一個對齊位置,才開始調(diào)整,比如3+2或者1+4,后者都需要另起(下邊的結(jié)構(gòu)體大小是8bytes),相關(guān)例子就多了,不贅述。為什么有些函數(shù)的參數(shù)是結(jié)構(gòu)體指針型如果函數(shù)的參數(shù)比較多,很容易產(chǎn)生“重復(fù)C語言代碼”,例如:(嵌入式開發(fā))中,C語言位結(jié)構(gòu)體用途詳解1.位結(jié)構(gòu)體類型設(shè)計uint_32

reserved_2

:8;

占用4個字節(jié),估計是uint_32在起作用,而這里寫的8位,只是我使用的有效位數(shù),另外24位空閑,如果在下面再定義一個uint_32reserved_3

:8,地址也是一樣的,都是以uint_32為單位取地址。

同理,上面的5個變量,共用一個地址就不足為奇了。而且有效位的分配不是連續(xù)進行的,例如SYMBOL_TYPE+reserved_1共9位,超過了一個字節(jié),索性系統(tǒng)就分配兩個字節(jié)給他們,每人一個;SYMBOL_NUMBER+SYMBOL_ACTIVE共8位,一個字節(jié)就能搞定。2、修改數(shù)據(jù)結(jié)構(gòu),驗證上述猜想3、分析結(jié)構(gòu)體內(nèi)部的數(shù)據(jù)域是否連續(xù),看下圖及結(jié)果

分析:這些數(shù)據(jù)域,整體相加一共32位,占用4個字節(jié)(不考慮數(shù)據(jù)對齊問題)。而實際確實是占用了4個字節(jié),唯一的原因就是:這些數(shù)據(jù)域以緊湊的方式鏈接,沒有任何空閑位。實際是不是這樣呢?看下圖和結(jié)果:

4、再次實驗,分析數(shù)據(jù)是否緊密鏈接,看下圖和結(jié)果

5、結(jié)構(gòu)體組合、共用體組合是否影響上述結(jié)論

總結(jié):1、在操作位結(jié)構(gòu)體時,要關(guān)注變量的位域是否在一個變量類型(uint_32或者uint_8)上,判斷占用空間大小。2、除了位域,還要關(guān)注變量定義類型,因為編譯器空間分配始終是按類型分配的,位域只是指出了有效位(小于類型占用空間),而且如果位域大于類型空間,編譯器直接報錯(如uint_8

test

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論