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

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

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

淺談void 型指針的高階用法

multisim ? 來(lái)源:嵌入式客棧 ? 作者: 逸珺 ? 2021-08-09 15:54 ? 次閱讀

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

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

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

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

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

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

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

3147083e-f874-11eb-9bcf-12bb97331649.png

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

但須注意的是:

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

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

31676c32-f874-11eb-9bcf-12bb97331649.png

void型指針解引用須做類(lèi)型指定。

類(lèi)型轉(zhuǎn)換的時(shí)候須注意類(lèi)型匹配。

另外,如果函數(shù)類(lèi)型可以是任意類(lèi)型的指針,則需將其參數(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 *, int, size_t);

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

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

/*模塊A中有這樣一個(gè)結(jié)構(gòu)體需要非易失存儲(chǔ)*/typedef struct _t_paras{

int language;/*語(yǔ)言種類(lèi)*/

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讀寫(xiě)函數(shù)實(shí)現(xiàn)的基礎(chǔ)上,將上述應(yīng)用數(shù)據(jù)按照一定順序存儲(chǔ)管理。那么更為理想的方式是什么呢?設(shè)計(jì)一個(gè)模塊專(zhuān)門(mén)負(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è)例子,可以延伸出很多類(lèi)似的應(yīng)用

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

免責(zé)聲明:本文素材來(lái)源網(wǎng)絡(luò),版權(quán)歸原作者所有。如涉及作品版權(quán)問(wèn)題,請(qǐng)與我聯(lián)系刪除。

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(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)投訴
  • UML
    UML
    +關(guān)注

    關(guān)注

    0

    文章

    122

    瀏覽量

    30876
  • C++
    C++
    +關(guān)注

    關(guān)注

    22

    文章

    2113

    瀏覽量

    73742
  • void
    +關(guān)注

    關(guān)注

    0

    文章

    23

    瀏覽量

    9883

原文標(biāo)題:void 型指針的高階用法,你掌握了嗎?

文章出處:【微信號(hào):A1411464185,微信公眾號(hào):multisim】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    javascript:void(0) 是否影響SEO優(yōu)化

    使用 javascript:void(0) 確實(shí)可能對(duì)SEO優(yōu)化產(chǎn)生負(fù)面影響 。以下是關(guān)于 javascript:void(0) 對(duì)SEO影響的具體分析: 搜索引擎爬蟲(chóng)的理解問(wèn)題 搜索引擎爬蟲(chóng)(如
    的頭像 發(fā)表于 12-31 16:08 ?173次閱讀

    javascript:void(0) 的作用是什么

    javascript:void(0) 在 HTML 和 JavaScript 中是一個(gè)常見(jiàn)的表達(dá)式,主要用來(lái)創(chuàng)建一個(gè)無(wú)操作的鏈接(通常是 標(biāo)簽)或者阻止默認(rèn)事件處理。具體來(lái)說(shuō),它的作用有以下幾點(diǎn)
    的頭像 發(fā)表于 12-31 15:55 ?224次閱讀

    C語(yǔ)言指針學(xué)習(xí)筆記

    本文從底層內(nèi)存分析,徹底讓讀者明白C語(yǔ)言指針的本質(zhì)。
    的頭像 發(fā)表于 11-05 17:40 ?270次閱讀
    C語(yǔ)言<b class='flag-5'>指針</b>學(xué)習(xí)筆記

    C語(yǔ)言指針運(yùn)算符詳解

    在C語(yǔ)言中,當(dāng)你有一個(gè)指向數(shù)組中某個(gè)元素的指針時(shí),你可以對(duì)該指針執(zhí)行某些算術(shù)運(yùn)算,例如加法或減法。這些運(yùn)算可以用來(lái)遍歷數(shù)組中的元素,如ptr[i]等價(jià)于*(ptr + i)。然而,如果你的操作使得指針指向了數(shù)組以外的位置(除了數(shù)
    的頭像 發(fā)表于 10-30 11:16 ?281次閱讀

    電流計(jì)指針偏轉(zhuǎn)方向是正極還是負(fù)極

    電流計(jì)指針的偏轉(zhuǎn)方向并非簡(jiǎn)單地指向正極或負(fù)極,而是取決于電流的流入方向以及電流計(jì)正負(fù)極的連接方式。以下是對(duì)這一問(wèn)題的分析: 一、電流流入方向與指針偏轉(zhuǎn)的關(guān)系 常規(guī)情況 : 對(duì)于常規(guī)的電流計(jì)(假設(shè)其
    的頭像 發(fā)表于 09-19 15:18 ?4225次閱讀

    C語(yǔ)言指針詳細(xì)解析

    ,pa,*pa); return 0; } 指針類(lèi)型 變量有不同的類(lèi)型,整型,浮點(diǎn)等等。指針同樣是有類(lèi)型的,定義如下。 char*pa = NULL; int* pb = NULL; short
    發(fā)表于 09-14 10:03

    面試???1:函數(shù)指針指針函數(shù)、數(shù)組指針指針數(shù)組

    在嵌入式開(kāi)發(fā)領(lǐng)域,函數(shù)指針、指針函數(shù)、數(shù)組指針指針數(shù)組是一些非常重要但又容易混淆的概念。理解它們的特性和應(yīng)用場(chǎng)景,對(duì)于提升嵌入式程序的效率和質(zhì)量至關(guān)重要。一、
    的頭像 發(fā)表于 08-10 08:11 ?947次閱讀
    面試???1:函數(shù)<b class='flag-5'>指針</b>與<b class='flag-5'>指針</b>函數(shù)、數(shù)組<b class='flag-5'>指針</b>與<b class='flag-5'>指針</b>數(shù)組

    面試中的高頻問(wèn)題:指針函數(shù)與函數(shù)指針,你能完美應(yīng)對(duì)嗎?

    一直覺(jué)得C語(yǔ)言較其他語(yǔ)言最偉大的地方就是C語(yǔ)言中的指針,有些人認(rèn)為指針很簡(jiǎn)單,而有些人認(rèn)為指針很難,當(dāng)然這里的對(duì)簡(jiǎn)單和難并不是等價(jià)于對(duì)指針的理解程度。為此在這里對(duì)C語(yǔ)言中的
    的頭像 發(fā)表于 06-22 08:11 ?1787次閱讀
    面試中的高頻問(wèn)題:<b class='flag-5'>指針</b>函數(shù)與函數(shù)<b class='flag-5'>指針</b>,你能完美應(yīng)對(duì)嗎?

    STM8默認(rèn)指針類(lèi)型完全可用滿(mǎn)足需求尋址到0X0000~9FFF的空間,為什么要強(qiáng)制使用@far的呢?

    在STM8的中斷文件中有這樣一句 typedef void @far (*interrupt_handler_t)(void); 1、字面意思:這個(gè)指針interrupt_handler_t所指
    發(fā)表于 05-09 06:51

    FPGA的高階應(yīng)用與發(fā)展方向討論

    FPGA可編程器件做高階應(yīng)用如圖像處理、語(yǔ)音識(shí)別等需要具備哪些能力,需要怎樣更有效從入門(mén)到精通 ? FPGA與當(dāng)下的AI發(fā)展結(jié)合的怎樣?大家可以交流討論
    發(fā)表于 03-30 18:09

    為什么指針之間不要隨意賦值呢?

    指針之間也不能隨意賦值。
    的頭像 發(fā)表于 03-28 17:13 ?729次閱讀
    為什么<b class='flag-5'>指針</b>之間不要隨意賦值呢?

    字符指針等變量等該如何初始化

     對(duì)于數(shù)值類(lèi)型的變量往往初始化為0,但對(duì)于其他類(lèi)型的變量,如字符、指針等變量等該如何初始化呢?
    的頭像 發(fā)表于 03-18 11:02 ?1566次閱讀

    函數(shù)指針與回調(diào)函數(shù)的應(yīng)用實(shí)例

    通常我們說(shuō)的指針變量是指向一個(gè)整型、字符或數(shù)組等變量,而函數(shù)指針是指向函數(shù)。 函數(shù)指針可以像一般函數(shù)一樣,用于調(diào)用函數(shù)、傳遞參數(shù)。
    的頭像 發(fā)表于 03-07 11:13 ?418次閱讀
    函數(shù)<b class='flag-5'>指針</b>與回調(diào)函數(shù)的應(yīng)用實(shí)例

    C語(yǔ)言的指針用法

    C語(yǔ)言編程中善用指針可以簡(jiǎn)化一些任務(wù)的處理,而對(duì)于一些任務(wù)(比如動(dòng)態(tài)內(nèi)存分配),必須要有指針才行的。也就是說(shuō)精通C指針編程是很有必要的,幫助你成為一名優(yōu)秀的Cer。
    發(fā)表于 03-05 14:22 ?381次閱讀
    C語(yǔ)言的<b class='flag-5'>指針</b><b class='flag-5'>用法</b>

    怎么理解指針指針

    怎么理解指針指針?其實(shí)這個(gè)概念并不難,只是把它放到實(shí)際應(yīng)用中,容易造成困擾。
    的頭像 發(fā)表于 02-23 16:46 ?1238次閱讀
    怎么理解<b class='flag-5'>指針</b>的<b class='flag-5'>指針</b>?