0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

了解嵌入式C:什么是結(jié)構(gòu)?

嵌入式星球 ? 2020-09-27 09:59 ? 次閱讀

本文提供了有關(guān)嵌入式C編程中的結(jié)構(gòu)的一些基本信息。
在介紹了結(jié)構(gòu)之后,我們將看一下這個(gè)強(qiáng)大的數(shù)據(jù)對(duì)象的一些重要應(yīng)用。然后,我們將檢查C語(yǔ)言語(yǔ)法以聲明結(jié)構(gòu)。最后,我們將簡(jiǎn)要介紹數(shù)據(jù)對(duì)齊要求。我們將看到,通過(guò)簡(jiǎn)單地重新排列其成員的順序,我們也許可以減小結(jié)構(gòu)的大小。

結(jié)構(gòu)體

邏輯上彼此相關(guān)的多個(gè)相同類型的變量可以分組為一個(gè)數(shù)組。在組上而不是自變量的集合上工作使我們可以整理數(shù)據(jù)并更方便地使用它。例如,我們可以定義以下數(shù)組來(lái)存儲(chǔ)將語(yǔ)音輸入數(shù)字化的ADC的最后50個(gè)樣本:

uint16_tvoice[50];

請(qǐng)注意,uint16_t是寬度為16位的無(wú)符號(hào)整數(shù)類型。這在C標(biāo)準(zhǔn)庫(kù)stdint.h中定義,該庫(kù)提供與系統(tǒng)規(guī)格無(wú)關(guān)的特定位長(zhǎng)的數(shù)據(jù)類型。

數(shù)組可用于對(duì)同一數(shù)據(jù)類型的多個(gè)變量進(jìn)行分組。如果不同數(shù)據(jù)類型的變量之間存在聯(lián)系怎么辦?我們可以在程序中將這些變量視為一組嗎?例如,假設(shè)我們需要指定 上面生成語(yǔ)音陣列的ADC的采樣率。我們可以定義一個(gè)float變量來(lái)存儲(chǔ)采樣率:

floatsample_rate;


盡管變量voicesample_rate彼此相關(guān),但它們被定義為兩個(gè)獨(dú)立變量。為了使這兩個(gè)變量相互關(guān)聯(lián),我們可以使用稱為結(jié)構(gòu)的C語(yǔ)言強(qiáng)大的數(shù)據(jù)構(gòu)造。結(jié)構(gòu)允許我們將不同的數(shù)據(jù)類型分組,并將它們作為單個(gè)數(shù)據(jù)對(duì)象處理。一個(gè)結(jié)構(gòu)可以包括不同種類的變量類型,例如其他結(jié)構(gòu),指向函數(shù)的指針,指向結(jié)構(gòu)的指針等。對(duì)于語(yǔ)音示例,我們可以使用以下結(jié)構(gòu):

structrecord{
uint16_tvoice[50];
floatsample_rate;
};

在這種情況下,我們有一個(gè)稱為record的結(jié)構(gòu),該結(jié)構(gòu) 具有兩個(gè)不同的成員或字段:第一個(gè)成員是uint16_t元素的數(shù)組,第二個(gè)成員是float類型的變量。語(yǔ)法以關(guān)鍵字struct開(kāi)頭。struct關(guān)鍵字后的單詞是一個(gè)可選名稱,用于以后引用該結(jié)構(gòu)。我們將在本文的其余部分中討論定義和使用結(jié)構(gòu)的其他細(xì)節(jié)。

為什么結(jié)構(gòu)很重要?


上面的示例指出了結(jié)構(gòu)的重要應(yīng)用,即定義了可以將不同類型的各個(gè)變量相互關(guān)聯(lián)的依賴于應(yīng)用的數(shù)據(jù)對(duì)象。這不僅導(dǎo)致處理數(shù)據(jù)的有效方式,而且使我們能夠?qū)崿F(xiàn)稱為數(shù)據(jù)結(jié)構(gòu)的專門結(jié)構(gòu)。
數(shù)據(jù)結(jié)構(gòu)可用于各種應(yīng)用程序,例如兩個(gè)嵌入式系統(tǒng)之間的消息傳遞以及將從傳感器收集的數(shù)據(jù)存儲(chǔ)在不連續(xù)的內(nèi)存位置中。


圖1.結(jié)構(gòu)可用于實(shí)現(xiàn)鏈表。
此外,當(dāng)程序需要訪問(wèn)內(nèi)存映射的微控制器外圍設(shè)備的寄存器時(shí),結(jié)構(gòu)是有用的數(shù)據(jù)對(duì)象。在下一篇文章中,我們將介紹結(jié)構(gòu)應(yīng)用程序。


圖2.STM32MCU存儲(chǔ)器映射。圖片由帶ARM嵌入式系統(tǒng)提供。
聲明結(jié)構(gòu)

要使用結(jié)構(gòu),我們首先需要指定一個(gè)結(jié)構(gòu)模板??紤]下面的示例代碼:

structrecord{
uint16_tvoice[4];
floatsample_rate;
};

這指定了用于創(chuàng)建此類型的將來(lái)變量的布局或模板。該模板包括一個(gè)uint16_t數(shù)組和一個(gè)float類型的變量。模板的名稱為record,它位于關(guān)鍵字struct之后。值得一提的是,沒(méi)有用于存儲(chǔ)結(jié)構(gòu)模板的內(nèi)存分配。僅在定義了基于此布局的結(jié)構(gòu)變量之后,才進(jìn)行內(nèi)存分配。以下代碼聲明 了上述模板的mic1變量:

structrecordmic1;

現(xiàn)在,為變量mic1分配了一部分內(nèi)存。它有空間存儲(chǔ)數(shù)組的四個(gè)uint16_t元素和一個(gè)float變量。

可以使用成員運(yùn)算符(。)訪問(wèn)結(jié)構(gòu)的成員。例如,以下代碼將100分配給數(shù)組的第一個(gè)元素,并將sample_rate的值復(fù)制到fs變量(該變量必須是float類型)。

mic1.voice[0]=100;
fs=mic1.sample_rate;


聲明結(jié)構(gòu)的其他方法
在上一節(jié)中,我們介紹了一種聲明結(jié)構(gòu)的方法。C語(yǔ)言支持其他一些格式,本節(jié)將進(jìn)行介紹。在整個(gè)程序中,您可能會(huì)堅(jiān)持使用一種格式,但有時(shí)可能會(huì)對(duì)其他格式有所幫助。

聲明結(jié)構(gòu)模板的一般語(yǔ)法為:

structtag_name{
type_1member_1;
type_2member_2;
…
type_nmember_n;

}variable_name;

TAG_NAME變量名是可選的標(biāo)識(shí)符。通常,我們會(huì)至少看到這兩個(gè)標(biāo)識(shí)符之一,但是在某些情況下,我們可以消除這兩個(gè)標(biāo)識(shí)符。

語(yǔ)法1:當(dāng)同時(shí)存在tag_namevariable_name時(shí),我們?cè)谀0搴竺娑x結(jié)構(gòu)變量。使用此語(yǔ)法,我們可以重寫以下示例:

structrecord{
uint16_tvoice[4];
floatsample_rate;
}mic1;

現(xiàn)在,如果我們需要定義另一個(gè)變量(mic2),我們可以編寫

structrecordmic2;

語(yǔ)法2:僅 包含variable_name。使用此語(yǔ)法,我們可以按以下方式重寫上一節(jié)中的示例:

struct{
uint16_tvoice[4];
floatsample_rate;
}mic1;

在這種情況下,我們必須在模板之后定義所有變量,而我們以后不能在程序中定義任何其他變量(因?yàn)槟0鍥](méi)有名稱,以后也不能引用它)。

語(yǔ)法3:在這種情況下,沒(méi)有tag_namevariable_name。以這種方式定義的結(jié)構(gòu)模板稱為匿名結(jié)構(gòu)??梢栽诹硪粋€(gè)結(jié)構(gòu)或聯(lián)合中定義匿名結(jié)構(gòu)。下面是一個(gè)示例:

structtest{
//Anonymousstructure
struct{
floatf;
chara;
};
}test_var;

要訪問(wèn)上述匿名結(jié)構(gòu)的成員,我們可以使用成員運(yùn)算符(。)。以下代碼將1.2分配給成員f

test_var.f=1.2;

由于該結(jié)構(gòu)是匿名的,因此我們僅使用一次成員運(yùn)算符訪問(wèn)其成員。如果它的名稱如下面的示例所示,我們將不得不兩次使用成員運(yùn)算符:

structtest{
struct{
floatf;
chara;
}nested;
}test_var;

在這種情況下,我們應(yīng)該使用以下代碼將1.2分配給f

test_var.nested.f=1.2;

如您所見(jiàn),匿名結(jié)構(gòu)可以使代碼更具可讀性,而又不那么冗長(zhǎng)。也可以將typedef關(guān)鍵字與結(jié)構(gòu)一起使用以定義新的數(shù)據(jù)類型。我們將在以后的文章中介紹這種方法。

結(jié)構(gòu)的內(nèi)存布局


C標(biāo)準(zhǔn)保證結(jié)構(gòu)的成員將按照在結(jié)構(gòu)中聲明成員的順序一個(gè)接一個(gè)地位于內(nèi)存中。第一個(gè)成員的內(nèi)存地址將與結(jié)構(gòu)本身的地址相同??紤]以下示例:


將分配四個(gè)存儲(chǔ)位置來(lái)存儲(chǔ)變量c,d,e和f。內(nèi)存位置的順序?qū)⑴c聲明成員的順序匹配:c的位置將具有最低的地址,然后是d,e,最后出現(xiàn)f。我們需要多少字節(jié)來(lái)存儲(chǔ)此結(jié)構(gòu)?考慮到變量的大小,我們知道至少需要1 + 4 + 1 + 2 = 8個(gè)字節(jié)來(lái)存儲(chǔ)此結(jié)構(gòu)。但是,如果我們將此代碼編譯為32位計(jì)算機(jī),則會(huì)令人驚訝地觀察到MyStruct的大小是12個(gè)字節(jié)而不是8個(gè)字節(jié)!這是由于以下事實(shí):編譯器在為結(jié)構(gòu)的不同成員分配內(nèi)存時(shí)具有某些約束。例如,一個(gè)32位整數(shù)只能存儲(chǔ)在其地址可被4整除的內(nèi)存位置。實(shí)施這種約束,稱為數(shù)據(jù)對(duì)齊要求,以使處理器更有效地訪問(wèn)變量。數(shù)據(jù)對(duì)齊會(huì)導(dǎo)致內(nèi)存布局浪費(fèi)一些空間(或填充)。僅在這里介紹該主題。我們將在本系列的下一篇文章中詳細(xì)介紹。


圖3.數(shù)據(jù)對(duì)齊會(huì)導(dǎo)致內(nèi)存布局中的空間浪費(fèi)(或填充)。
意識(shí)到數(shù)據(jù)對(duì)齊要求后,我們也許可以重新排列結(jié)構(gòu)中成員的順序,并使內(nèi)存使用效率更高。例如,如果我們按如下所示重寫上述結(jié)構(gòu),則在32位計(jì)算機(jī)上,其大小將減小為8個(gè)字節(jié)。

structTest2{
uint32_td;
uint16_tf;
uint8_tc;
uint8_te;
}MyStruct;

對(duì)于受內(nèi)存限制的嵌入式系統(tǒng),將數(shù)據(jù)對(duì)象的大小從12個(gè)字節(jié)減少到8個(gè)字節(jié)可節(jié)省大量資金,尤其是當(dāng)程序需要許多此類數(shù)據(jù)對(duì)象時(shí)。
下一篇文章將更詳細(xì)地討論數(shù)據(jù)對(duì)齊,并研究在嵌入式系統(tǒng)中使用結(jié)構(gòu)的一些示例。

概要

  • 結(jié)構(gòu)允許我們定義依賴于應(yīng)用程序的數(shù)據(jù)對(duì)象,這些對(duì)象可以將不同類型的各個(gè)變量相互關(guān)聯(lián)。這導(dǎo)致了一種有效的數(shù)據(jù)處理方法。

  • 稱為數(shù)據(jù)結(jié)構(gòu)的專用結(jié)構(gòu)可用于各種應(yīng)用程序,例如兩個(gè)嵌入式系統(tǒng)之間的消息傳遞以及將從傳感器收集的數(shù)據(jù)存儲(chǔ)在不連續(xù)的內(nèi)存位置中。

  • 當(dāng)我們需要訪問(wèn)存儲(chǔ)器映射的微控制器外設(shè)的寄存器時(shí),結(jié)構(gòu)很有用。

  • 通過(guò)重新排列結(jié)構(gòu)中成員的順序,我們也許可以使內(nèi)存使用效率更高。


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    嵌入式系統(tǒng)的體系結(jié)構(gòu)包括哪些

    嵌入式系統(tǒng)的體系結(jié)構(gòu)通常是一個(gè)復(fù)雜而精細(xì)的架構(gòu),旨在滿足特定應(yīng)用需求,同時(shí)兼顧系統(tǒng)的可靠性、效率、成本和體積等多方面因素。以下是對(duì)嵌入式系統(tǒng)體系結(jié)構(gòu)的詳細(xì)解析,包括其主要組成部分、層次
    的頭像 發(fā)表于 09-02 15:25 ?672次閱讀

    嵌入式常用數(shù)據(jù)結(jié)構(gòu)有哪些

    嵌入式編程中,數(shù)據(jù)結(jié)構(gòu)的選擇和使用對(duì)于程序的性能、內(nèi)存管理以及開(kāi)發(fā)效率都具有重要影響。嵌入式系統(tǒng)由于資源受限(如處理器速度、內(nèi)存大小等),因此對(duì)數(shù)據(jù)結(jié)構(gòu)的選擇和使用尤為關(guān)鍵。以下是
    的頭像 發(fā)表于 09-02 15:25 ?358次閱讀

    嵌入式系統(tǒng)怎么學(xué)?

    C++或者Python。這些語(yǔ)言在嵌入式系統(tǒng)開(kāi)發(fā)中都被廣泛應(yīng)用。 3、微處理器/微控制器架構(gòu):學(xué)習(xí)常見(jiàn)的微處理器和微控制器架構(gòu),如ARM、AVR、PIC等,了解其特性和應(yīng)用場(chǎng)景。 4、
    發(fā)表于 07-02 10:10

    如何提升嵌入式編程能力?

    其他硬件的數(shù)據(jù)手冊(cè),了解其特性和編程接口。 6. 學(xué)習(xí)低級(jí)編程:嵌入式編程常常需要直接與硬件交互,因此學(xué)習(xí)如何進(jìn)行低級(jí)編程,如結(jié)構(gòu)體、枚舉類型、指針操作、位操作、內(nèi)存映射I/O等。 7. 掌握
    發(fā)表于 06-21 10:01

    嵌入式系統(tǒng)軟硬件基礎(chǔ)知識(shí)大全

    可以存儲(chǔ)臨時(shí)數(shù)據(jù)。了解這些存儲(chǔ)器的特點(diǎn)和層次結(jié)構(gòu),有助于我們優(yōu)化嵌入式系統(tǒng)的性能和存儲(chǔ)需求。嵌入式系統(tǒng)的外設(shè)接口和通信協(xié)議是其與外部世界交互的關(guān)鍵。常見(jiàn)的接口類型包括UART、SPI、
    發(fā)表于 05-09 14:12

    嵌入式主板,你了解多少?

    嵌入式主板,也稱為嵌入式計(jì)算機(jī)主板,是一種專門設(shè)計(jì)用于嵌入式系統(tǒng)的計(jì)算機(jī)主板。與臺(tái)式機(jī)和筆記本電腦中使用的常規(guī)主板不同,嵌入式主板設(shè)計(jì)用于集成到更大的電子設(shè)備中,例如汽車、醫(yī)療設(shè)備或自
    的頭像 發(fā)表于 04-17 15:11 ?1379次閱讀

    如何成為一名嵌入式C語(yǔ)言高手?

    相關(guān)教材、參加在線課程或者參考編程書籍來(lái)系統(tǒng)地學(xué)習(xí)C語(yǔ)言的基礎(chǔ)知識(shí),并通過(guò)編寫簡(jiǎn)單的程序進(jìn)行實(shí)踐。 二、深入了解嵌入式系統(tǒng)的硬件架構(gòu)和工作原理嵌入式系統(tǒng)通常包含微控制器或微處理器等硬件
    發(fā)表于 04-07 16:03

    如何成為一名嵌入式C語(yǔ)言高手?

    相關(guān)教材、參加在線課程或者參考編程書籍來(lái)系統(tǒng)地學(xué)習(xí)C語(yǔ)言的基礎(chǔ)知識(shí),并通過(guò)編寫簡(jiǎn)單的程序進(jìn)行實(shí)踐。 二、深入了解嵌入式系統(tǒng)的硬件架構(gòu)和工作原理嵌入式系統(tǒng)通常包含微控制器或微處理器等硬件
    發(fā)表于 03-25 14:12

    嵌入式軟件開(kāi)發(fā)應(yīng)該掌握哪些知識(shí)?

    掌握的知識(shí) 1.基礎(chǔ)知識(shí) 1.1 c/c++編程語(yǔ)言和數(shù)據(jù)結(jié)構(gòu) C/C++ 是嵌入式系統(tǒng)中常用的
    發(fā)表于 02-19 11:23

    嵌入式學(xué)習(xí)步驟

    開(kāi)發(fā)。 嵌入式學(xué)習(xí)步驟總結(jié)如下: (1).確定目標(biāo)平臺(tái):選擇適合您要開(kāi)發(fā)的嵌入式系統(tǒng)的硬件平臺(tái)。這取決于您要控制的設(shè)備以及您需要執(zhí)行的任務(wù)。 (2).選擇編程語(yǔ)言:嵌入式系統(tǒng)通常使用C
    發(fā)表于 02-02 15:24

    聊一聊嵌入式C語(yǔ)言

    作為一名嵌入式軟件開(kāi)發(fā)者,熟練掌握嵌入式C語(yǔ)言對(duì)我的日常工作至關(guān)重要。
    的頭像 發(fā)表于 01-22 09:28 ?509次閱讀

    嵌入式自學(xué)好書推薦

    工作經(jīng)驗(yàn)的薪資可達(dá)10-15k;而擁有3年以上工作經(jīng)驗(yàn)的薪資可在15-25k范圍內(nèi)。 嵌入式開(kāi)發(fā)的前期入門知識(shí)主要包括以下四個(gè)方面: 1.電路知識(shí):學(xué)習(xí)基礎(chǔ)的電路、模擬電路和數(shù)字電路,了解基礎(chǔ)器件、放大
    發(fā)表于 01-11 15:13

    嵌入式C語(yǔ)言的結(jié)構(gòu)特點(diǎn)

    過(guò)程中,不論是基于寄存器開(kāi)發(fā)還是基于庫(kù)開(kāi)發(fā),深入理解和掌握嵌入式C語(yǔ)言的函數(shù)、指針、結(jié)構(gòu)體是學(xué)習(xí)STM32的關(guān)鍵。嵌入式C語(yǔ)言的
    的頭像 發(fā)表于 11-24 16:16 ?616次閱讀
    <b class='flag-5'>嵌入式</b><b class='flag-5'>C</b>語(yǔ)言的<b class='flag-5'>結(jié)構(gòu)</b>特點(diǎn)

    嵌入式系統(tǒng)的C語(yǔ)言

    電子發(fā)燒友網(wǎng)站提供《嵌入式系統(tǒng)的C語(yǔ)言.doc》資料免費(fèi)下載
    發(fā)表于 11-18 14:39 ?2次下載
    <b class='flag-5'>嵌入式</b>系統(tǒng)的<b class='flag-5'>C</b>語(yǔ)言

    c語(yǔ)言嵌入式開(kāi)發(fā)

    電子發(fā)燒友網(wǎng)站提供《c語(yǔ)言嵌入式開(kāi)發(fā).zip》資料免費(fèi)下載
    發(fā)表于 11-17 14:11 ?2次下載
    <b class='flag-5'>c</b>語(yǔ)言<b class='flag-5'>嵌入式</b>開(kāi)發(fā)