国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

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

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

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

淺談void 型指針的高階用法

multisim ? 來源:嵌入式客棧 ? 作者: 逸珺 ? 2021-08-09 15:54 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

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

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

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

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

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

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

對于空指針的解引用,你如不信,就來看看栗子:

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

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

但須注意的是:

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

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

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

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 *, int, size_t);

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

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

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

int language;/*語言種類*/

char SN[20]; /*產(chǎn)品序列號*/

}T_PARAS;

T_PARAS sysParas;

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

float kp;

float ki;

float kd;

float T;

}T_PID;

T_PID pidParas;

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

typedef struct _t_nv_layout{

void * pElement; /*參數(shù)地址*/

int length; /*參數(shù)長度*/

}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ù)邏輯與后臺的隔離解耦。做到了通用性。這里就比較巧妙的利用了void *指針的特性。如果對于該設(shè)計(jì)思想,在進(jìn)一步延伸,將底層的抽象在做一層封裝,將更細(xì)節(jié)的底層實(shí)現(xiàn)細(xì)節(jié)隔離抽象,比如:

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

將存儲介質(zhì)抽象,比如是EEPROM/DATA FLASH等。。。

。。。。

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

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

利用void *指針,將業(yè)務(wù)數(shù)據(jù)與底層存儲實(shí)現(xiàn)了抽象解耦

利用分層抽象實(shí)現(xiàn)了代碼具有良好的可移植性

利用函數(shù)指針實(shí)現(xiàn)了C++等高級語言的虛函數(shù)定義接口的思想

統(tǒng)一接口底層實(shí)現(xiàn)抽象,實(shí)現(xiàn)了驅(qū)動(dòng)分層的思想

void *指針由這個(gè)例子,可以延伸出很多類似的應(yīng)用

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

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

編輯:jq

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

    關(guān)注

    0

    文章

    123

    瀏覽量

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

    關(guān)注

    22

    文章

    2124

    瀏覽量

    77112
  • void
    +關(guān)注

    關(guān)注

    0

    文章

    23

    瀏覽量

    10238

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

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

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

掃碼添加小助手

加入工程師交流群

    評論

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

    傳遞一個(gè)無符號的 long 指針給函數(shù)

    C語言允許傳遞指針給函數(shù),只需要簡單地聲明函數(shù)參數(shù)為指針類型即可。 下面的實(shí)例中,我們傳遞一個(gè)無符號的 long 指針給函數(shù),并在函數(shù)內(nèi)改變這個(gè)值: 實(shí)例 #include #i
    發(fā)表于 01-27 11:51

    指針與函數(shù)詳解

    ,和函數(shù)入?yún)⑹?b class='flag-5'>指針有什么好處呢??? #include #include void plusfunction(int a,int b,int *p); int main() { int *p
    發(fā)表于 01-23 06:02

    函數(shù)指針介紹

    (char *data, int len){ int voltage = 0; ···//其他功能代碼 return voltage;}int main(void){ pFunc_tpHandler = read_voltage;//使用類型pFunc_t來定義函數(shù)指針
    發(fā)表于 01-21 08:11

    函數(shù)指針與回調(diào)函數(shù)解讀

    變量存放的是一個(gè)地址,在32位單片機(jī)中,任何類型的指針變量都存放的是一個(gè)大小為4字節(jié)的地址。 inta; < = > void cal_sum(void
    發(fā)表于 01-19 07:34

    指針難學(xué)的4點(diǎn)原因分析

    難點(diǎn)1. 討厭的星號 定義指針變量p時(shí),都會(huì)加個(gè)*號。在用到指針變量p時(shí),也會(huì)加個(gè)*號。比如以下代碼: int main() { int *p; p = malloc(sizeof(int
    發(fā)表于 01-16 06:12

    Modbus RTU 四大高階技巧:工程師實(shí)戰(zhàn)分享的協(xié)議進(jìn)階用法

    除了常規(guī)的數(shù)據(jù)采集,Modbus RTU 還有哪些不尋常的“高階玩法”?下面分享幾個(gè)有意思的用法。 1. 暗度陳倉 通過4X保持寄存器傳文件 在僅支持 Modbus RTU 協(xié)議的串口連接下,可通過
    的頭像 發(fā)表于 01-14 11:02 ?265次閱讀
    Modbus RTU 四大<b class='flag-5'>高階</b>技巧:工程師實(shí)戰(zhàn)分享的協(xié)議進(jìn)階<b class='flag-5'>用法</b>

    C語言函數(shù)指針的六個(gè)高級的應(yīng)用場景

    函數(shù)指針是一種非常強(qiáng)大的編程工具,它可以讓我們以更加靈活的方式編寫程序。在本文中,我們將介紹 6 個(gè)函數(shù)指針的高級應(yīng)用場景,并貼出相應(yīng)的代碼案例和解釋。 回調(diào)函數(shù) 回調(diào)函數(shù)是指在某個(gè)事件發(fā)生時(shí)被
    發(fā)表于 01-04 12:25

    指針的基礎(chǔ)

    1. int va; 這是一個(gè)整型變量,32位CPU的話,占有32個(gè)bite 2. int *va; 這是一個(gè)整型指針變量,用于存放一個(gè)整型變量的地址 3. int **va; 這是一個(gè)整型
    發(fā)表于 12-15 06:06

    指針鏈介紹

    = p->pos; pos->x = 0; pos->y = 0; pos->z = 0; } 另一種方法是在Object結(jié)構(gòu)中直接包含Point3類的數(shù)據(jù),這能完全消除對Point3使用指針操作。
    發(fā)表于 12-12 07:14

    函數(shù)指針指針函數(shù)的區(qū)別

    指針的函數(shù),即本質(zhì)是一個(gè)函數(shù)。函數(shù)返回類型是某一類指針   類型標(biāo)識符 *函數(shù)名(參數(shù)表)   int *f(x,y);   首先它是一個(gè)函數(shù),只不過這個(gè)函數(shù)的返回值是一個(gè)地址值。函數(shù)返回值必須
    發(fā)表于 12-12 06:34

    函數(shù)指針的概念

    函數(shù)指針是指向函數(shù)的指針變量。 通常我們說的指針變量是指向一個(gè)整型、字符或數(shù)組等變量,而函數(shù)指針是指向函數(shù)。 函數(shù)
    發(fā)表于 12-11 08:10

    如何用函數(shù)指針調(diào)用函數(shù)

    (void) { int(*p)(int, int);//定義一個(gè)函數(shù)指針 int a, b, c; p = Max;//把函數(shù)Max賦給指針變量p, 使p指向Max函數(shù) printf(\"
    發(fā)表于 12-11 06:26

    UIAbility組件基本用法說明

    UIAbility組件基本用法 UIAbility組件的基本用法包括:指定UIAbility的啟動(dòng)頁面以及獲取UIAbility的上下文UIAbilityContext。 指定UIAbility
    發(fā)表于 05-16 06:32

    函數(shù)指針的六個(gè)常見應(yīng)用場景

    函數(shù)指針在嵌入式開發(fā)中有著廣泛的應(yīng)用,它讓代碼更加靈活,減少冗余,提高可擴(kuò)展性。很多時(shí)候,我們需要根據(jù)不同的情況動(dòng)態(tài)調(diào)用不同的函數(shù),而函數(shù)指針正是實(shí)現(xiàn)這一需求的重要工具。本文將介紹六個(gè)常見的函數(shù)指針
    的頭像 發(fā)表于 04-07 11:58 ?1476次閱讀
    函數(shù)<b class='flag-5'>指針</b>的六個(gè)常見應(yīng)用場景

    永磁同步電機(jī)自適應(yīng)高階滑模Type-2模糊控制

    針對永磁同步電機(jī)數(shù)學(xué)模型不確定問題,提出一種自適應(yīng)高階滑模Type-2模糊控制方法。采用積分滑模面二階滑模控制律,保持傳統(tǒng)滑模控制的魯棒性并實(shí)現(xiàn)不含不確定高階輸入輸出有限時(shí)間穩(wěn)定;不需要預(yù)先確定干擾
    發(fā)表于 03-27 11:54