chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

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

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

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

循環(huán)隊(duì)列C語言面向?qū)ο髮?shí)現(xiàn)

技術(shù)讓夢(mèng)想更偉大 ? 來源:CSDN-夏日白云 ? 2023-04-04 09:47 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

前言

學(xué)習(xí)完《Test-Driven Development for Embedded C》后對(duì)C語言中的面向?qū)ο箝_發(fā)又多了一層理解,過兩天可能專門出個(gè)博客來說說新的理解。

而我已經(jīng)按照更面向?qū)ο蟮姆椒ù蟾牧嗽瓉淼哪莻€(gè)環(huán)形緩沖區(qū)模塊,考慮到整個(gè)結(jié)構(gòu)已經(jīng)完全不同了,所以直接棄用了原來那個(gè)模塊,新模塊直接重新開始記版本號(hào)。

Buffer模塊為了通用,定義了前后都可以進(jìn)出,想當(dāng)成隊(duì)列來用比如可以入隊(duì)用BackIn,出隊(duì)用FrontOut;相當(dāng)成棧來用比如可以入棧用BackIn,出棧用BackOut。當(dāng)然,第三篇中我會(huì)給出Queue類,并把Buffer類適配為了Queue類,這樣可能用起來更舒服些,雖然當(dāng)然有額外的開銷。

緩沖區(qū)介紹

實(shí)際項(xiàng)目中我們常常會(huì)需要一小塊區(qū)域來暫存一些數(shù)據(jù),可能是用來緩存使用,可能是用來線程間通信,我們把其稱為緩沖區(qū)/Buffer。這塊區(qū)域可能是先入先出的(隊(duì)列)也可能是先入后出的(棧),但反正最后都可以抽象為一個(gè)可以在頭或尾存取數(shù)據(jù)的內(nèi)存區(qū)域。

緩沖區(qū)的具體實(shí)現(xiàn)方式一般有鏈表和數(shù)組,當(dāng)不能確定需要的緩沖區(qū)大小時(shí)使用鏈表較好,能確定時(shí)使用數(shù)組可以節(jié)省很多動(dòng)態(tài)分配內(nèi)存的開銷。

而在具體實(shí)現(xiàn)上我們常常會(huì)使用環(huán)形緩沖區(qū),環(huán)形緩沖區(qū)就是一個(gè)邏輯上環(huán)形的區(qū)域,因?yàn)槠?邏輯上)是環(huán)形的,所以不需要在內(nèi)部元素變動(dòng)的時(shí)候需要移動(dòng)內(nèi)部剩下的元素。這樣就使元素進(jìn)出頭尾的時(shí)間復(fù)雜度只有O(1),效率十分的高,在通信等領(lǐng)域應(yīng)用頻繁。

模塊類圖

以下是目前整個(gè)模塊的類圖。

a0e3e45c-d246-11ed-bfe3-dac502259ad0.png

模塊設(shè)計(jì)思路簡介

緩沖區(qū)是個(gè)很常見的需求,即對(duì)一塊邏輯上環(huán)形的區(qū)域的頭尾進(jìn)行In和Out操作,以緩存各種類型的數(shù)據(jù)。對(duì)調(diào)用者來說,并不需要知道其使用的模塊/類內(nèi)部實(shí)際是怎么實(shí)現(xiàn)的,只需要知道這個(gè)模塊/類實(shí)現(xiàn)哪幾個(gè)方法,這幾個(gè)方法是干什么用的就行(其實(shí)就是所謂的面向接口編程)。因此,需要為環(huán)形緩沖區(qū)定義通用的接口。

在一個(gè)略大的項(xiàng)目中我們常常需要在多處使用環(huán)形緩沖區(qū)。所以在這次的實(shí)現(xiàn)中我并沒有使用單例的方式來實(shí)現(xiàn)這個(gè)模塊,而是直接默認(rèn)是多例的方式,不同的實(shí)現(xiàn)各自提供Create方法來返回對(duì)象引用,Destroy方法來銷毀。

實(shí)際開發(fā)中有時(shí)會(huì)需要混用多種實(shí)現(xiàn),比如有的你希望使用一個(gè)RAM數(shù)組,有的想用鏈表,甚至有的是使用Flash來存儲(chǔ)的等。而只要接口相同,調(diào)用者不需要知道具體的實(shí)現(xiàn)細(xì)節(jié),只需要你給他傳遞一個(gè)實(shí)現(xiàn)了這個(gè)接口的對(duì)象就行。這其實(shí)就實(shí)現(xiàn)了不同模塊間的解耦。而為了實(shí)現(xiàn)在同一個(gè)C工程中調(diào)用同一個(gè)接口能實(shí)際調(diào)用不同的實(shí)現(xiàn)(即多態(tài)),這就需要使用虛表技術(shù)。這里就不展開了。

再考慮一個(gè)很實(shí)際的需求,在CodeWarrior對(duì)S12X的編程中,為了節(jié)省非分頁的RAM,我常想要把這個(gè)環(huán)形緩沖區(qū)放在分頁的RAM中,這樣,兩種環(huán)形緩沖區(qū)可能唯一的差別就是具體訪問某個(gè)元素的方式是使用普通指針還是rptr指針,如果分別寫一個(gè)實(shí)現(xiàn),就會(huì)有大量的冗余代碼。出于程序員的自我修養(yǎng),肯定得把這些通用的部分給抽象出來。用繼承的方式實(shí)現(xiàn)代碼的復(fù)用。

好像前面說的有點(diǎn)混亂。簡而言之,就是按照面向?qū)ο蟮乃枷?,定義不同層次的接口,通過虛表實(shí)現(xiàn)多態(tài),通過類繼承盡可能復(fù)用代碼,最終實(shí)現(xiàn)這個(gè)完整的模塊。

我們可以照著類圖看看目前我的抽象方式。首先所有對(duì)象都會(huì)有個(gè)Destroy方法,所以object接口對(duì)其進(jìn)行了定義。這里我沒有專門再定義一個(gè)Object虛類,后面可能會(huì)抽象出來。而最主要的一個(gè)基類叫做Container(容器),所有的容器都要實(shí)現(xiàn)getCapacity和getCount接口。而isEmpty和isFull其實(shí)是通過調(diào)用這兩個(gè)虛方法返回結(jié)果的。

而后虛類BufferTYPE繼承了Container虛類,并(虛)實(shí)現(xiàn)了環(huán)形緩沖區(qū)的7個(gè)通用方法,包括檢查頭/尾元素(Front和Back)、從頭/尾取出元素(FrontOut和BackOut)、往頭/尾放入元素(FrontOut和BackOut)以及清空緩沖區(qū)(Cleanup)。

TYPE只是一個(gè)代號(hào),使用時(shí)要替換成實(shí)際類型。目前我實(shí)現(xiàn)了UINT8、UINT16、UINT32的。如果需要使用其他類型,如果類型的size為8、16、32,建議直接適配一下就好(其實(shí)就是對(duì)同樣size的進(jìn)行強(qiáng)制類型轉(zhuǎn)換一下,BufferChar給出了一個(gè)示例),這樣可以盡可能地實(shí)現(xiàn)代碼復(fù)用,如果是其他特殊的,那就照著源代碼中的自己擴(kuò)展一下吧,主要是C語言沒有模板功能,只好直接在名字中標(biāo)記上類型來區(qū)分。

然后繼承的BufferTYPEIndexed虛類要實(shí)現(xiàn)索引器接口,其是所有能通過索引直接訪問的Buffer的基類。

BufferArrayShare類繼承BufferTYPEIndexed類并實(shí)現(xiàn)了所有通過類數(shù)組操作來實(shí)現(xiàn)的Buffer類的通用部分,其調(diào)用索引器來訪問數(shù)組元素,這樣就實(shí)現(xiàn)了不同訪問方式的復(fù)用。與之相對(duì)的則是子類BufferTypeArray和BufferTypeArrayR分別實(shí)現(xiàn)了位于直接訪問區(qū)的數(shù)組和分頁區(qū)數(shù)組的索引器。

而末尾的3個(gè)實(shí)現(xiàn)類則主要負(fù)責(zé)內(nèi)存的管理部分,動(dòng)態(tài)分配實(shí)例并實(shí)現(xiàn)對(duì)應(yīng)的Destroy方法,然后調(diào)用父類的Init方法來實(shí)現(xiàn)完整的類。項(xiàng)目中可以同時(shí)使用這幾個(gè)類。

當(dāng)然,因?yàn)楦叨鹊拿嫦驅(qū)ο?,?dǎo)致有大量的小文件,這其實(shí)和面向?qū)ο笳Z言提供的各種類有一堆文件一個(gè)道理。好在使用起來還是很方便的。

如果只是使用的話建議不需要具體了解內(nèi)部的實(shí)現(xiàn),根據(jù)類圖了解下繼承關(guān)系,看看每個(gè)類的接口的描述。然后直接調(diào)用實(shí)例的方法就行。那一堆小文件就直接全部拖到項(xiàng)目中就好。(PS.沒有用到的類是不會(huì)鏈接進(jìn)去占用內(nèi)存的,所以直接扔進(jìn)項(xiàng)目就好了,沒用到就沒用到。)

現(xiàn)在會(huì)有這些文件。

a0fd80c4-d246-11ed-bfe3-dac502259ad0.png

編程約定

接口定義在.h頭文件中,如名字中帶有Private則代表其中的接口為private或protect的,非開發(fā)者不應(yīng)該使用,否則為public的,供給用戶使用。

由于C語言本身沒有OO這個(gè)概念,所以類的方法以這種方式命名,這樣可以很直觀地知道是哪個(gè)類的方法:

類名_方法();

另,對(duì)于多例的類,第一個(gè)參數(shù)為被調(diào)用方法的實(shí)例,其后跟其他參數(shù)。

如BufferUINT8的Back方法的簽名如下:

uint8_t BufferUINT8_Back   (BufferUINT8 buf);
1

子類實(shí)例可以直接調(diào)用父類方法。如:

uint8_t arr[ARRSIZE];
BufferUINT8ArrayR buf;
buf = BufferUINT8ExternalArray_Create(arr, ARRSIZE);
// 緩沖區(qū)前面放入55
BufferUINT8_FrontIn((BufferUINT8)buf,55);
// 現(xiàn)在緩沖區(qū)內(nèi)元素為[ 55 ]

示例程序

這里已隱去不重要的代碼:

#include 
#include "BufferExternalArrayR.h"
#include "BufferExternalArray.h"
#include "BufferMallocArray.h"

#pragma push
#pragma DATA_SEG __RPAGE_SEG PAGED_RAM
static uint8_t PagedArray[300];
#pragma pop
static uint8_t nonPagedArray[50];

static void BufferTest(BufferUINT8 buf){
 int i;
 printf("sizeof buffer:%u
FrontIn: 0 to 9
BackOut: ",BufferUINT8_getCapacity(buf));
 for(i = 0; i < 10; i++)
 ? ?BufferUINT8_FrontIn(buf,i);
 ?for(i = 0; i < 10; i++)
 ? ?printf(" %u",BufferUINT8_BackOut(buf));
 ?printf("
");
}
void main(void) {
 ?BufferUINT8 buf1,buf2,buf3;
 ?buf1 = BufferUINT8ExternalArrayR_Create(PagedArray,sizeof(PagedArray));
 ?buf2 = BufferUINT8ExternalArray_Create(nonPagedArray,sizeof(nonPagedArray));
 ?buf3 = BufferUINT8MallocArray_Create(40);
 ?printf("buf1(BufferExternalArrayR) Test:
");
 ?BufferTest(buf1);
 ?printf("buf2(BufferExternalArray) Test:
");
 ?BufferTest(buf2);
 ?printf("buf3(BufferMallocArray) Test:
");
 ?BufferTest(buf3);
 ?for(;;) {
  } 
}

a111f216-d246-11ed-bfe3-dac502259ad0.png

可以看到,上例中BufferTest并不知道傳遞給他的BufferUINT8的具體實(shí)現(xiàn),它只需要知道這個(gè)實(shí)例實(shí)現(xiàn)了BufferUINT8的方法就可以正確地對(duì)其進(jìn)行操作,從而實(shí)現(xiàn)了解耦。

另,上例中的BufferUINT8_getCapacity其實(shí)是因?yàn)槲以贐uffer模塊的頭文件中用宏的方式給Container_getCapacity起了別名,這樣用起來就更順手了對(duì)吧。

審核編輯:湯梓紅

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

原文標(biāo)題:循環(huán)隊(duì)列C語言面向?qū)ο髮?shí)現(xiàn)

文章出處:【微信號(hào):技術(shù)讓夢(mèng)想更偉大,微信公眾號(hào):技術(shù)讓夢(mèng)想更偉大】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    C語言實(shí)現(xiàn)面向對(duì)象的方式 C++中的class的運(yùn)行原理

    這里主要介紹下在C語言中是如何實(shí)現(xiàn)面向對(duì)象。知道了C語言實(shí)
    發(fā)表于 10-21 09:00 ?1516次閱讀

    嵌入式C語言面向對(duì)象編程---多態(tài)

    前兩篇文章主要講述了 C 語言面向對(duì)象編程– 封裝和繼承。本篇文章繼續(xù)來討論一下,如何使用 C 語言實(shí)現(xiàn)
    發(fā)表于 10-31 14:41 ?1383次閱讀

    單片機(jī)C語言 -- 基于結(jié)構(gòu)體的面向對(duì)象編程技巧

    :系統(tǒng)初始化后,進(jìn)入主循環(huán),通過結(jié)構(gòu)體調(diào)用system文件的函數(shù)。2、結(jié)構(gòu)體類型定義定義1個(gè)變量與2個(gè)函數(shù)指針。單片機(jī)C語言面向對(duì)象編程,
    發(fā)表于 02-04 21:48

    如何用C語言實(shí)現(xiàn)面向對(duì)象編程

    1 用C語言實(shí)現(xiàn)面向對(duì)象編程GOF的《設(shè)計(jì)模式》一書的副標(biāo)題叫做“可復(fù)用面向對(duì)象軟件的基礎(chǔ)”,從
    發(fā)表于 07-12 07:24

    c語言實(shí)現(xiàn)面向對(duì)象編程 精選資料分享

    差異。在語法上,C語言支持的oop(面向對(duì)象)機(jī)制比較薄弱,但完全可以使用c語言寫出
    發(fā)表于 09-02 07:46

    面向對(duì)象編程語言的特點(diǎn)

    工業(yè)控制系統(tǒng)的PLC程序中也可以采用這種設(shè)計(jì)思想,雖然我們無法實(shí)現(xiàn)面向對(duì)象的很多優(yōu)秀特點(diǎn)如“繼承”,甚至于它根本就不具備面向對(duì)象編程
    發(fā)表于 09-08 07:44

    C++語言和面向對(duì)象程序設(shè)計(jì)教程

    C++語言和面向對(duì)象程序設(shè)計(jì)代表了旨在使計(jì)算機(jī)問題解更加符合人的思維活動(dòng),是軟件開發(fā)方法的一場(chǎng)革命;面向對(duì)象建模和
    發(fā)表于 03-02 08:00 ?6次下載

    為什么要用C語言實(shí)現(xiàn)面向對(duì)象

    對(duì)象的編程語言,但面向對(duì)象的概念是在C語言階段就有了,而且應(yīng)用到了很多地方,比如某些操作系統(tǒng)內(nèi)核
    的頭像 發(fā)表于 11-05 18:05 ?2107次閱讀
    為什么要用<b class='flag-5'>C</b><b class='flag-5'>語言實(shí)現(xiàn)</b><b class='flag-5'>面向</b><b class='flag-5'>對(duì)象</b>

    如何用C語言實(shí)現(xiàn)面向對(duì)象編程OOP?

    解釋區(qū)分一下C語言和OOP我們經(jīng)常說C語言面向過程的,而C++是
    的頭像 發(fā)表于 12-18 16:18 ?2820次閱讀

    C語言是如何實(shí)現(xiàn)面向對(duì)象

    C++是 面向對(duì)象 的編程語言,但面向對(duì)象的概念是在C
    的頭像 發(fā)表于 12-24 17:08 ?2w次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語言</b>是如何<b class='flag-5'>實(shí)現(xiàn)</b><b class='flag-5'>面向</b><b class='flag-5'>對(duì)象</b>的

    為什么要用C語言實(shí)現(xiàn)面向對(duì)象

    對(duì)象的編程語言,但面向對(duì)象的概念是在C語言階段就有了,而且應(yīng)用到了很多地方,比如某些操作系統(tǒng)內(nèi)核
    的頭像 發(fā)表于 06-04 17:44 ?2787次閱讀
    為什么要用<b class='flag-5'>C</b><b class='flag-5'>語言實(shí)現(xiàn)</b><b class='flag-5'>面向</b><b class='flag-5'>對(duì)象</b>呢

    為什么要用C語言實(shí)現(xiàn)面向對(duì)象呢?

    對(duì)象的編程語言,但面向對(duì)象的概念是在C語言階段就有了,而且應(yīng)用到了很多地方,比如某些操作系統(tǒng)內(nèi)核
    的頭像 發(fā)表于 06-12 17:55 ?2105次閱讀
    為什么要用<b class='flag-5'>C</b><b class='flag-5'>語言實(shí)現(xiàn)</b><b class='flag-5'>面向</b><b class='flag-5'>對(duì)象</b>呢?

    嵌入式C語言面向對(duì)象編程應(yīng)用及優(yōu)勢(shì)

    既然面向對(duì)象是一種編程思想,而編程語言只是一種工具,那么,思想與工具之間就不存在一種強(qiáng)耦合的關(guān)系,C++可以面向
    發(fā)表于 11-10 12:00 ?2211次閱讀
    嵌入式<b class='flag-5'>C</b><b class='flag-5'>語言</b><b class='flag-5'>面向</b><b class='flag-5'>對(duì)象</b>編程應(yīng)用及優(yōu)勢(shì)

    C語言是怎么面向對(duì)象編程

    在嵌入式開發(fā)中,C/C++語言是使用最普及的,在C++11版本之前,它們的語法是比較相似的,只不過C++提供了
    的頭像 發(fā)表于 02-14 13:57 ?2351次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>語言</b>是怎么<b class='flag-5'>面向</b><b class='flag-5'>對(duì)象</b>編程

    淺談C語言面向對(duì)象編程思想

    C語言是一種面向過程的語言,但是也可以用結(jié)構(gòu)體和函數(shù)指針來模擬面向對(duì)象的特性,比如封裝、繼承和多
    發(fā)表于 11-02 12:27 ?1691次閱讀