當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 嵌入式客棧
[導(dǎo)讀]關(guān)注、星標(biāo)嵌入式客棧,干貨及時(shí)送達(dá) [導(dǎo)讀] 要比較靈活的使用C語(yǔ)言實(shí)現(xiàn)一些高層級(jí)的框架時(shí),需要掌握一些進(jìn)階編程技巧,這篇來(lái)談?wù)剉oid指針的一些妙用。測(cè)試環(huán)境采用 IAR for ARM 8.40.1 推薦一首中文歌曲<<后來(lái)>>,英文翻唱<> 來(lái)自瑞典歌手Sofia Kall

關(guān)注、星標(biāo)嵌入式客棧,干貨及時(shí)送達(dá)

[導(dǎo)讀] 要比較靈活的使用C語(yǔ)言實(shí)現(xiàn)一些高層級(jí)的框架時(shí),需要掌握一些進(jìn)階編程技巧,這篇來(lái)談?wù)剉oid指針的一些妙用。測(cè)試環(huán)境采用 IAR for ARM 8.40.1

推薦一首中文歌曲<<后來(lái)>>,英文翻唱<<life>>

來(lái)自瑞典歌手Sofia Kallgern:

什么是void指針

void指針一般被稱為通用指針或叫泛指針。它是C語(yǔ)言關(guān)于純粹地址的一種約定。當(dāng)某個(gè)指針是void型指針時(shí),所指向的對(duì)象不屬于任何類型。 因?yàn)関oid指針不屬于任何類型,則不可以對(duì)其進(jìn)行算術(shù)運(yùn)算,比如自增,編譯器不知道其自增需要增加多少。比如char *型指針,自增一定是指針指向的地址加1,short *型指針自增,則偏移2。

在C/C++中,在任意時(shí)刻都可以使用其它類型指針來(lái)代替void指針,或者用void指針來(lái)代替其他類型指針。

由這些特性就可以衍生出很多比較有用的技巧。指針的本質(zhì),是其值為一個(gè)地址,那么延伸一下:

當(dāng)使用關(guān)鍵字void聲明指針變量時(shí),它將成為通用指針變量。任何數(shù)據(jù)類型(char,int,float等)的任何變量的地址都可以賦值給void指針變量。

對(duì)指針變量的解引用,使用間接運(yùn)算符*達(dá)到目的。但是在使用空指針的情況下,需要轉(zhuǎn)換指針變量以解引用。這是因?yàn)榭罩羔槢](méi)有與之關(guān)聯(lián)的數(shù)據(jù)類型。編譯器無(wú)法知道void指針指向的數(shù)據(jù)類型。因此,要獲取由void指針指向的數(shù)據(jù),需要使用在void指針位置內(nèi)保存的正確類型的數(shù)據(jù)進(jìn)行類型轉(zhuǎn)換。

對(duì)于空指針的解引用,你如不信,就來(lái)看看栗子:

看到了吧,直接解引用編譯不過(guò),因?yàn)榫幾g器蒙了。

但須注意的是:

  • 不同的編譯器對(duì)void指針處理是不一樣的,如IAR,ANSI C,VC對(duì)上述都將出錯(cuò),而GNU指定“void”的算法操作與“char”一致,因此上述寫法在GNU則可以編譯

所以做個(gè)類型轉(zhuǎn)換,修正如下:

  • void型指針解引用須做類型指定。
  • 類型轉(zhuǎn)換的時(shí)候須注意類型匹配。

另外,如果函數(shù)類型可以是任意類型的指針,則需將其參數(shù)定義為void *指針,例如string.h中關(guān)于內(nèi)存操作的函數(shù)集:

  __EFF_NENW1NW2   __ATTRIBUTES   int       memcmp(const void *, const void *,
                                                   size_t)
;
  __EFF_NENR1NW2R1 __DEPREC_ATTRS void *    memcpy(void *_Restrict,
                                                   const void *_Restrict,
                                                   size_t)
;
  __EFF_NENR1NW2R1 __DEPREC_ATTRS void *    memmove(void *, const void *,
                                                    size_t)
;
  __EFF_NENR1R1    __DEPREC_ATTRS void *    memset(void *, intsize_t);

非易失存儲(chǔ)管理應(yīng)用

在單片機(jī)開(kāi)發(fā)中,往往需要實(shí)現(xiàn)數(shù)據(jù)的非易失存儲(chǔ)。所謂非易失存儲(chǔ),就是數(shù)據(jù)改寫后在掉電后仍然能保持。哪些是非易失存儲(chǔ)介質(zhì)呢?比如EEPROM,FLASH等都屬于非易失存儲(chǔ)介質(zhì)。

比如一個(gè)產(chǎn)品里面有很多各種各樣的參數(shù),且分布在各個(gè)子系統(tǒng)文件中。舉個(gè)栗子:

/*模塊A中有這樣一個(gè)結(jié)構(gòu)體需要非易失存儲(chǔ)*/
typedef struct _t_paras{
   int language;/*語(yǔ)言種類*/
   char SN[20]; /*產(chǎn)品序列號(hào)*/
}T_PARAS;
T_PARAS sysParas;

/*模塊B中有這樣一個(gè)結(jié)構(gòu)體需要非易失存儲(chǔ)*/
typedef struct _t_pid{
   float kp;
   float ki;
   float kd;
   float T;
}T_PID;
T_PID pidParas;

面對(duì)這樣一個(gè)需求,要實(shí)現(xiàn)非易失存儲(chǔ),我在將底層的EEPROM/FLASH讀寫函數(shù)實(shí)現(xiàn)的基礎(chǔ)上,將上述應(yīng)用數(shù)據(jù)按照一定順序存儲(chǔ)管理。那么更為理想的方式是什么呢?設(shè)計(jì)一個(gè)模塊專門負(fù)責(zé)存儲(chǔ)非易失數(shù)據(jù)。比如:

typedef struct _t_nv_layout{
     void * pElement; /*參數(shù)地址*/
     int    length;   /*參數(shù)長(zhǎng)度*/
}T_NV_LAYOUT;
/*參數(shù)映射表*/
T_NV_LAYOUT nvLayout[]={
    {&sysParas,sizeof(T_PARAS)},/*參數(shù)映射記錄*/
    {&pidParas,sizeof(T_PID)},
    ...
};
/*參數(shù)映射表記錄條數(shù)*/
#define NV_RECORD_NUMBER  (sizeof(nvLayout)/sizeof(T_NV_LAYOUT))
void nv_load(T_NV_LAYOUT *pLayout,int nvAddr,int number);
void nv_store(T_NV_LAYOUT *pLayout,int nvAddr,int number);

將上述設(shè)計(jì)思想,利用UML描述一下:

在上述基礎(chǔ)上,我們只需要設(shè)計(jì)硬件層抽象,即可設(shè)計(jì)出一個(gè)可行的、比較通用的NV管理子系統(tǒng),這樣設(shè)計(jì)出的子系統(tǒng)忽略了業(yè)務(wù)數(shù)據(jù),僅僅將其處理為數(shù)據(jù),并不關(guān)心其業(yè)務(wù)意義。實(shí)現(xiàn)了業(yè)務(wù)邏輯與后臺(tái)的隔離解耦。做到了通用性。這里就比較巧妙的利用了void *指針的特性。如果對(duì)于該設(shè)計(jì)思想,在進(jìn)一步延伸,將底層的抽象在做一層封裝,將更細(xì)節(jié)的底層實(shí)現(xiàn)細(xì)節(jié)隔離抽象,比如:

  • 抽象I2C/SPI EEPROM,將其對(duì)上層的調(diào)用接口統(tǒng)一,那么如果你的系統(tǒng)原本是存儲(chǔ)在I2C EEPROM中,現(xiàn)在做一個(gè)新項(xiàng)目,你需要使用另外一種SPI接口的EEPROM,則只需要實(shí)現(xiàn)相應(yīng)的底層處理函數(shù)即可。
  • 將存儲(chǔ)介質(zhì)抽象,比如是EEPROM/DATA FLASH等...
  • ....

那么怎么做到底層抽象呢,我們可以利用函數(shù)指針定義統(tǒng)一的接口,具體部署時(shí),只需要將實(shí)現(xiàn)函數(shù)的指針賦值給對(duì)應(yīng)的函數(shù)指針即可,這樣就做到了接口的抽象統(tǒng)一。其實(shí)這就是驅(qū)動(dòng)模型的一個(gè)簡(jiǎn)易雛形。

總結(jié)一下

這篇文章引入了一些編程思想,對(duì)于單片機(jī)/嵌入式進(jìn)階編程比較有用:

  • 利用void *指針,將業(yè)務(wù)數(shù)據(jù)與底層存儲(chǔ)實(shí)現(xiàn)了抽象解耦
  • 利用分層抽象實(shí)現(xiàn)了代碼具有良好的可移植性
  • 利用函數(shù)指針實(shí)現(xiàn)了C++等高級(jí)語(yǔ)言的虛函數(shù)定義接口的思想
  • 統(tǒng)一接口底層實(shí)現(xiàn)抽象,實(shí)現(xiàn)了驅(qū)動(dòng)分層的思想
  • void *指針由這個(gè)例子,可以延伸出很多類似的應(yīng)用

啟示:一些語(yǔ)言細(xì)節(jié)如果深入了解其背后的機(jī)理,可以得到很多比較巧妙的應(yīng)用。

留言區(qū)

END

果喜歡右下點(diǎn)個(gè)在看,也會(huì)讓我倍感鼓舞

往期精彩推薦,點(diǎn)擊即可閱讀




▲抽象思想解讀Linux進(jìn)程描述符
讀U-Boot源碼-C語(yǔ)言編程大法總結(jié)篇一
讀U-Boot源碼-C語(yǔ)言編程技巧總結(jié)篇二
基于Buildroot的Linux構(gòu)建之根文件系統(tǒng)
手把手教系列之移動(dòng)平均濾波器C實(shí)現(xiàn)
手把手教系列之IIR數(shù)字濾波器設(shè)計(jì)實(shí)現(xiàn)
手把手教系列之梳狀濾波器設(shè)計(jì)實(shí)現(xiàn)
Linux 內(nèi)核架構(gòu)分析

關(guān)注置頂:掃描左下二維碼關(guān)注公眾號(hào)加星

討論加群:掃描右下二維碼添加,發(fā)送“加群”

關(guān)注

加群

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉