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

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

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

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

宏的高級(jí)用法

工程師 ? 來(lái)源:嵌入式軟件實(shí)戰(zhàn)派 ? 作者:嵌入式軟件實(shí)戰(zhàn)派 ? 2020-09-15 15:59 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

對(duì)于條件/分支處理的程序設(shè)計(jì),我們慣性地會(huì)選擇switch-case或者if-else,這也是C語(yǔ)言老師當(dāng)初教的。以下,我們用一個(gè)播放器的例子來(lái)說(shuō)明,要實(shí)現(xiàn)的功能如下:

收到用戶(hù)操作播放器命令請(qǐng)求,如“播放”、“暫停”等,程序要對(duì)命令作區(qū)分;

針對(duì)不同的命令請(qǐng)求,作相應(yīng)的處理;

輸出必要的輔助信息。

首先,將命令定義成enum類(lèi)型:

enum { CMD_PLAY, CMD_PAUSE, CMD_STOP, CMD_PLAY_NEXT, CMD_PLAY_PREV, };

然后,用switch-case的分支處理:

switch(cmd) { case CMD_PLAY: // handle play command break; case CMD_PAUSE: // handle pause command break; case CMD_STOP: // handle stop command break; case CMD_PLAY_NEXT: // handle play next command break; case CMD_PLAY_PREV: // handle play previous command break; default: break; }

實(shí)際上,這也沒(méi)什么毛病。但是,時(shí)間長(zhǎng)了,需求不斷變更,程序不斷迭代,這個(gè)switch-case會(huì)變得非常冗長(zhǎng)而很難維護(hù)。你不相信?我曾經(jīng)見(jiàn)到過(guò)》1000行的類(lèi)似這樣的代碼。如果讓你接手維護(hù)這樣的代碼,你內(nèi)心會(huì)不會(huì)狂奔著萬(wàn)千***?

但是,我不敢更改這個(gè)祖?zhèn)鞯膕witch-case啊,那么小心翼翼地將這些命令處理封裝成函數(shù)。像這樣:

#define FUNC_IN() printf(“enter %s \r\n”, __FUNCTION__) void func_cmd_play(void* p) { FUNC_IN(); } void func_cmd_pause(void* p) { FUNC_IN(); } void func_cmd_stop(void* p) { FUNC_IN(); } void func_cmd_play_next(void* p) { FUNC_IN(); } void func_cmd_play_prev(void* p) { FUNC_IN(); } void player_cmd_handle(int cmd, void* p) { switch(cmd) { case CMD_PLAY: func_cmd_play(p); break; case CMD_PAUSE: func_cmd_pause(p); break; case CMD_STOP: func_cmd_stop(p); break; case CMD_PLAY_NEXT: func_cmd_play_next(p); break; case CMD_PLAY_PREV: func_cmd_play_prev(p); break; default: break; } }

后來(lái),甲方還是不斷地更改需求,導(dǎo)致播放器的命令越來(lái)越多,幾十個(gè)上百個(gè)了……痛定思痛,我——要——改——革??!

解放switch-case/if-else

腦子里想來(lái)想去,度娘上翻來(lái)翻去,于是定義了個(gè)結(jié)構(gòu)體:

typedef void(*pFunc)(void* p); typedef struct { tCmd cmd; pFunc func; }tPlayerStruct; tPlayerStruct player_cmd_func[] = { {CMD_PLAY, func_cmd_play) }, {CMD_PAUSE, func_cmd_pause) }, {CMD_STOP, func_cmd_stop) }, {CMD_PLAY_NEXT, func_cmd_play_next) }, {CMD_PLAY_PREV, func_cmd_play_prev) }, }; #define ARR_LEN(arr)sizeof(arr)/sizeof(arr[0]) void player_cmd_handle(int cmd, void* p) { for(int i = 0; i 《 ARR_LEN(player_cmd_func); i++) { if(player_cmd_func[i].cmd == cmd && NULL != player_cmd_func[i].func) { player_cmd_func[i].func(p); break; } } }

咦?好像代碼簡(jiǎn)潔了不少哦,改完之后好有成就感。

身為追求卓越的程序員,我還是有點(diǎn)不滿(mǎn)意,可不可以不用for循環(huán),直接使用player_cmd_func[cmd].func(p);,這樣還可以免去查詢(xún)的步驟,提高效率?

想法是好的,如果上面的程序不用for循環(huán),有可能數(shù)組越界,還有如果有命令增加,順序下標(biāo)不對(duì)應(yīng)的問(wèn)題。

之前,我在《C語(yǔ)言的奇技淫巧之五》中的第50條提到過(guò)這個(gè)方法,還立了個(gè)flag,我要用MACRO寫(xiě)個(gè)更高效更好的代碼!

使用X-MACRO

你聽(tīng)說(shuō)過(guò)X-MACRO么?聽(tīng)過(guò)沒(méi)聽(tīng)過(guò)都沒(méi)關(guān)系,來(lái),我們一起耍起來(lái)!

MACRO或者說(shuō)宏定義(書(shū)上或者規(guī)范上一般講預(yù)處理)基本原因都很簡(jiǎn)單,看看就很容易學(xué)會(huì)??雌饋?lái)好像也是平淡無(wú)奇,似乎沒(méi)什么大作用。但是,你可別小看它,我們將其安上個(gè)“X”就很牛逼(不知道這個(gè)是啥傳統(tǒng),對(duì)于某些函數(shù)的擴(kuò)展,喜歡在其前面或后面加個(gè)“X”,然后這個(gè)函數(shù)比之前的函數(shù)功能強(qiáng)大很多,Windows里面的Api就有這案例)。

X-MACRO是一種可靠維護(hù)代碼或數(shù)據(jù)的并行列表的技術(shù),其相應(yīng)項(xiàng)必須以相同的順序出現(xiàn)。它們?cè)谥辽倌承┝斜頍o(wú)法通過(guò)索引組成的地方(例如編譯時(shí))最有用。此類(lèi)列表的示例尤其包括數(shù)組的初始化,枚舉常量和函數(shù)原型的聲明,語(yǔ)句序列和切換臂的生成等。X-MACRO的使用可以追溯到1960年代。它在現(xiàn)代C和C ++編程語(yǔ)言中仍然有用。

X-MACRO應(yīng)用程序包括兩部分:

列表元素的定義。

擴(kuò)展列表以生成聲明或語(yǔ)句的片段。

該列表由一個(gè)宏或頭文件(名為L(zhǎng)IST)定義,該文件本身不生成任何代碼,而僅由一系列調(diào)用宏(通常稱(chēng)為“ X”)與元素的數(shù)據(jù)組成。LIST的每個(gè)擴(kuò)展都在X定義之前加上一個(gè)list元素的語(yǔ)法。LIST的調(diào)用會(huì)為列表中的每個(gè)元素?cái)U(kuò)展X。

好了,少扯淡,我們是實(shí)戰(zhàn)派,搞點(diǎn)有用的東西。

對(duì)于MACRO有幾個(gè)明顯的特征:

MACRO實(shí)際上就是做替換工作;

宏定義的替換工作是在編譯前進(jìn)行的,即預(yù)編譯;

宏定義可以用undef取消,然后再重新反復(fù)定義。

我們就用這幾個(gè)特征把MACRO耍到牛X起來(lái)!

#define X(a,b)a int x = DEF_X(1,2); #undef DEF_X #define DEF_X(a,b)b int y = DEF_X(1,2);

從上面可以看到,這個(gè)x和y的值是不一樣的。

于是可以定義一個(gè)這樣的宏:

#define CMD_FUNC \ DEF_X(CMD_PLAY, func_cmd_play) \ DEF_X(CMD_PAUSE, func_cmd_pause) \ DEF_X(CMD_STOP, func_cmd_stop) \ DEF_X(CMD_PLAY_NEXT, func_cmd_play_next) \ DEF_X(CMD_PLAY_PREV, func_cmd_play_prev) \

CMD的enum可以這樣定義:

typedef enum { #define DEF_X(a,b) a, CMD_FUNC #undef DEF_X CMD_MAX }tCmd;

預(yù)編譯后,這實(shí)際上就是這樣的:

typedef enum { CMD_PLAY, CMD_PAUSE, CMD_STOP, CMD_PLAY_NEXT, CMD_PLAY_PREV, CMD_MAX }tCmd;

接著,我們按這種套路定義一個(gè)函數(shù)指針數(shù)組:

const pFunc player_funcs[] = { #define DEF_X(a,b) b, CMD_FUNC #undef DEF_X };

甚至,我們可以定義一個(gè)命令的字符串,以作打印信息用:

const char* str_cmd[] = { #define DEF_X(a,b) #a, CMD_FUNC #undef DEF_X };

只要這個(gè)DEF_X(a,b)里面的a和b是對(duì)應(yīng)關(guān)系正確的,CMD_FUNC后面的元素順序是所謂了,這個(gè)比前面的結(jié)構(gòu)體有天然優(yōu)勢(shì)。這樣,我們就可以直接用下標(biāo)開(kāi)始操作了:

void player_cmd_handle(tCmd cmd, void* p) { if(cmd 《 CMD_MAX) { player_funcs[cmd](p); } else { printf(“Command(%d) invalid!\n”, cmd); } }

這不僅提高了效率,還不用擔(dān)心命令的順序問(wèn)題。

這種X-MACRO的用法對(duì)分支結(jié)構(gòu),特別是消息命令的處理特別的方便高效。

以下附上該案例的完整測(cè)試源碼:

#include 《stdio.h》 #define FUNC_IN() printf(“enter %s \r\n”, __FUNCTION__) #define CMD_FUNC \ DEF_X(CMD_PLAY, func_cmd_play) \ DEF_X(CMD_PAUSE, func_cmd_pause) \ DEF_X(CMD_STOP, func_cmd_stop) \ DEF_X(CMD_PLAY_NEXT, func_cmd_play_next) \ DEF_X(CMD_PLAY_PREV, func_cmd_play_prev) \ typedef enum { #define DEF_X(a,b) a, CMD_FUNC #undef DEF_X CMD_MAX }tCmd; const char* str_cmd[] = { #define DEF_X(a,b) #a, CMD_FUNC #undef DEF_X }; typedef void(*pFunc)(void* p); void func_cmd_play(void* p) { FUNC_IN(); } void func_cmd_pause(void* p) { FUNC_IN(); } void func_cmd_stop(void* p) { FUNC_IN(); } void func_cmd_play_next(void* p) { FUNC_IN(); } void func_cmd_play_prev(void* p) { FUNC_IN(); } const pFunc player_funcs[] = { #define DEF_X(a,b) b, CMD_FUNC #undef DEF_X }; void player_cmd_handle(tCmd cmd, void* p) { if(cmd 《 CMD_MAX) { player_funcs[cmd](p); } else { printf(“Command(%d) invalid!\n”, cmd); } } int main(void) { player_cmd_handle(CMD_PAUSE, (void*)0); player_cmd_handle(100, (void*)0); return 0; }

留個(gè)作業(yè)題:

如何靈活地將一個(gè)結(jié)構(gòu)體的內(nèi)容系列化到一個(gè)數(shù)組中,以及如何將一個(gè)數(shù)組的內(nèi)容解系列化到結(jié)構(gòu)體中?

例如,將以下結(jié)構(gòu)體s的內(nèi)容copy到data中(別老想著memcopy哦):

typedef struct STRUCT_DATA { int a; char b; short c; }tStruct;tStruct s; unsigned char data[100];

聲明:本文內(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)投訴
  • 嵌入式
    +關(guān)注

    關(guān)注

    5186

    文章

    20160

    瀏覽量

    329027
  • 宏匯編器
    +關(guān)注

    關(guān)注

    0

    文章

    7

    瀏覽量

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

掃碼添加小助手

加入工程師交流群

    評(píng)論

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

    泰科技與ADI正式簽署合作備忘錄

    近日,南京泰半導(dǎo)體科技股份有限公司(以下簡(jiǎn)稱(chēng)“泰科技”)與全球領(lǐng)先的高性能半導(dǎo)體公司ADI正式簽署合作備忘錄,雙方將在半導(dǎo)體測(cè)試與精密信號(hào)測(cè)量領(lǐng)域展開(kāi)持續(xù)深度合作,共同推動(dòng)高性能測(cè)試系統(tǒng)的技術(shù)創(chuàng)新與市場(chǎng)應(yīng)用落地。
    的頭像 發(fā)表于 12-02 09:09 ?934次閱讀

    C語(yǔ)言的printf基本用法介紹

    大家只需要掌握最基本的用法,以后隨著編程知識(shí)的學(xué)習(xí),我們會(huì)逐步介紹更加高級(jí)用法,最終讓大家完全掌握 printf。
    發(fā)表于 11-12 07:04

    干貨放送!集物流運(yùn)輸沖擊記錄儀直播精選問(wèn)答集錦,你想知道的都在這

    集技術(shù)主題直播于8月20日?qǐng)A滿(mǎn)結(jié)束,感謝各位熱情參與!直播中,集科技高級(jí)技術(shù)工程師針畢工對(duì)不同物流運(yùn)輸?shù)膶?shí)際應(yīng)用場(chǎng)景,為大家分析如何高效監(jiān)測(cè)運(yùn)輸環(huán)境,保障貨物安全交付和厘清貨損責(zé)任。直播中,我們
    的頭像 發(fā)表于 09-02 17:03 ?586次閱讀
    干貨放送!<b class='flag-5'>宏</b>集物流運(yùn)輸沖擊記錄儀直播精選問(wèn)答集錦,你想知道的都在這

    干貨放送!集科技物聯(lián)網(wǎng)技術(shù)直播精選問(wèn)答集錦,建議收藏!

    集直播圓滿(mǎn)結(jié)束,感謝各位熱情參與!直播上,集科技多位高級(jí)技術(shù)工程師針對(duì)不同產(chǎn)線的實(shí)際應(yīng)用場(chǎng)景,為大家分析如何突破瓶頸,提高生產(chǎn)效率。直播中,我們收到了眾多提問(wèn),展現(xiàn)了大家對(duì)集物聯(lián)
    的頭像 發(fā)表于 08-08 18:24 ?455次閱讀
    干貨放送!<b class='flag-5'>宏</b>集科技物聯(lián)網(wǎng)技術(shù)直播精選問(wèn)答集錦,建議收藏!

    明電子創(chuàng)業(yè)板IPO獲得受理

    近日,深交所官網(wǎng)顯示,成都明電子股份有限公司(以下簡(jiǎn)稱(chēng)“明電子”)創(chuàng)業(yè)板IPO獲得受理。
    的頭像 發(fā)表于 06-06 11:16 ?962次閱讀

    Vicor助力發(fā)打造主動(dòng)懸架電源系統(tǒng)

    廈門(mén)發(fā)電聲股份有限公司(發(fā))打造業(yè)內(nèi)性能卓越的主動(dòng)懸架電源系統(tǒng),旨在將長(zhǎng)期以來(lái)僅見(jiàn)于豪華車(chē)型的功能引入中端車(chē)型。發(fā)成功突破困擾知名汽車(chē)技術(shù)供應(yīng)商幾十年的技術(shù)瓶頸,在滿(mǎn)足主動(dòng)懸架系統(tǒng)對(duì)尺寸、重量及瞬態(tài)性能的嚴(yán)苛需求的同時(shí),兼
    的頭像 發(fā)表于 06-04 15:24 ?926次閱讀

    harmony OS NEXT-Navagation基本用法

    # Navagation基本用法 > Navigation組件是路由導(dǎo)航的根視圖容器,一般作為Page頁(yè)面的根容器使用,其內(nèi)部默認(rèn)包含了標(biāo)題欄,內(nèi)容欄和公工具欄,其中內(nèi)容區(qū)默認(rèn)首頁(yè)顯示導(dǎo)航內(nèi)容
    的頭像 發(fā)表于 04-27 17:39 ?735次閱讀

    EPLAN 2.6 3D制作與使用

    電子發(fā)燒友網(wǎng)站提供《EPLAN 2.6 3D制作與使用.pdf》資料免費(fèi)下載
    發(fā)表于 03-11 15:53 ?1次下載

    誠(chéng)創(chuàng)新獲B+輪融資追加投資

    近日,北京誠(chéng)創(chuàng)新科技有限公司傳來(lái)喜訊,成功獲得B+輪融資的追加投資,本輪追加投資由國(guó)資基金山東省文化發(fā)展投資基金注入。 此前,誠(chéng)創(chuàng)新已經(jīng)獲得了由亦莊國(guó)投和云洲資本領(lǐng)投的1億元人民幣B+輪投資。而
    的頭像 發(fā)表于 02-13 09:58 ?664次閱讀

    WEBENCH電源高級(jí)分析

    電子發(fā)燒友網(wǎng)站提供《WEBENCH電源高級(jí)分析.pdf》資料免費(fèi)下載
    發(fā)表于 01-21 14:53 ?0次下載
    WEBENCH電源<b class='flag-5'>高級(jí)</b>分析

    常州市領(lǐng)導(dǎo)蒞臨微科技走訪調(diào)研

    近日,常州市市長(zhǎng)周偉一行蒞臨江蘇微科技股份有限公司(以下簡(jiǎn)稱(chēng)微科技)新竹廠區(qū)走訪調(diào)研。
    的頭像 發(fā)表于 01-08 16:24 ?996次閱讀

    定義后面能不能加分號(hào)

    用define定義的,最后需不需要加分號(hào)?
    的頭像 發(fā)表于 01-06 16:35 ?949次閱讀

    keil在Debug的高級(jí)用法

    第一節(jié)軟件說(shuō)明Keil提供了包括C編譯器、匯編、鏈接器、庫(kù)管理和一個(gè)功能強(qiáng)大的仿真調(diào)試器等在內(nèi)的完整開(kāi)發(fā)方案,通過(guò)一個(gè)集成開(kāi)發(fā)環(huán)境(μVision)將這些部分組合在一起。目前軟件對(duì)中文的支持不友好
    的頭像 發(fā)表于 12-26 21:01 ?2730次閱讀
    keil在Debug的<b class='flag-5'>高級(jí)</b><b class='flag-5'>用法</b>

    景智駕總部落地衢州

    近日,景智駕衢州總部落地儀式在南孔圣地衢州東方橋庵里大酒店盛大舉行!衢州智造新城黨工委副書(shū)記、管委會(huì)常務(wù)副主任巫建民與景智駕創(chuàng)始人及CEO劉飛龍博士共同為落地儀式剪彩。
    的頭像 發(fā)表于 12-24 17:10 ?1203次閱讀

    DAC7562的CLR引腳怎么用法?可以懸空嗎?

    DAC7562的CLR引腳怎么用法?可以懸空嗎?能不能詳細(xì)解釋一下?謝謝
    發(fā)表于 12-17 08:16