色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

宏的使用:用宏##粘貼函數,然后用函數指針查找執行的操作

strongerHuang ? 來源:strongerHuang ? 作者:良知猶存 ? 2020-11-20 15:49 ? 次閱讀

宏的使用,大家經常會用,但是一般只是簡單定義一個符號常量,類似于#define WHEEL_SCALE_MM 0.53f、#define LOG_I(tag, text_fmt, ...) log_i(tag, text_fmt, ##__VA_ARGS__) ,但是除此之外還有宏還有個##粘貼作用,可以配合#define這個常量表達式,可以做成一個宏定義指針函數列表,繼而查詢執行函數。

話不多說,我們開始今天的分享,首先還是會進行一下常規的描述,再分享"##"粘貼的妙用。

一、#define的常規操作

#define預處理器指令和其他預處理器指令一樣, 以#號作為一行的開
始。ANSI和后來的標準都允許#號前面有空格或制表符, 而且還允許在#和
指令的其余部分之間有空格。但是舊版本的C要求指令從一行最左邊開始,
而且#和指令其余部分之間不能有空格。指令可以出現在源文件的任何地
方, 其定義從指令出現的地方到該文件末尾有效。我們大量使用#define指令來定義明示常量(manifest constant) (也叫做符號常量) 。 預處理器指令從#開始運行, 到后面的第1個換行符為止。也就是說, 指
令的長度僅限于一行。然而,在預處理開始前, 編譯器會把多行物理行處理為一行邏輯行。

一般我們會用#define 來進行明示常量,或者做一個簡單的宏替換函數

#define RX_BUF_SIZE 30#define MBEDTLS_DES_C /*數據加密*/#define ExitIsr Encoder_Isr void Encoder_Isr(void){ g.dir_count += (g.dir == 1)? 1 : -1; }每行#define(邏輯行) 都由3部分組成。第1部分是#define指令本身。第
2部分是選定的縮寫, 也稱為宏。有些宏代表值(如本例) , 這些宏被稱為
類對象宏。C 語言還有類函數宏, 稍后討論。宏的名稱中不允許有空格, 而且必須遵循C變量的命名規則:只能使用字符、 數字和下劃線(_) 字符, 而且首字符不能是數字。第3部分(指令行的其余部分) 稱為替換列表或替換體。
一旦預處理器在程序中找到宏的實例后, 就會用替換體代替該宏。從宏變成最終替換文本的過程稱為宏展開。注意, 可以在#define行使用標準C注釋。如前所述, 每條注釋都會被一個空格代替。

此外我們還會比較多的使用變宏參

通過把宏參數列表中最后的參數寫成省略號(即, 3個點...) 來實現這
一功能。這樣, 預定義宏_ _VA_ARGS_ _可用在替換部分中, 表明省略號代表什么。

#define PR(...) printf(_ _VA_ARGS_ _)

假設稍后調用該宏:

PR("Howdy");PR("weight = %d, shipping = $%.2f ", wt, sp);

對于第1次調用, _ _VA_ARGS_ _展開為1個參數:"Howdy"。
對于第2次調用, _ _VA_ARGS_ _展開為3個參數:"weight = %d,
shipping = $%.2f "、 wt、 sp。

因此, 展開后的代碼是:

printf("Howdy");printf("weight = %d, shipping = $%.2f ", wt, sp);

二、#define配合##使用

很多人應該都知道"##"的用法,它被稱為預處理的粘合劑,與#運算符類似,##運算符可用于類函數宏的替換部分。而且,##還可以用于對象宏的替換部分。##運算符可以把兩個記號組合成一個記號。

#definedef_u32_array(__name,__size)uint32_tarray_##__name[__size];

實際中,我們可以這樣使用:

def_u32_array(sample_buffer, 64)

宏展開的效果是:

uint32_tarray_sample_buffer[64];

同樣類比于初始化一個數組,我們也可以粘貼形成一個函數

下面就是在Linux內核里面的源代碼:

其中這個__pcpu_size_call_return宏,通過##粘貼選擇要使用的raw_cpu_read_x 函數。

#define __pcpu_size_call_return(stem, variable) ({ typeof(variable) pscr_ret__; __verify_pcpu_ptr(&(variable)); switch(sizeof(variable)) { case 1: pscr_ret__ = stem##1(variable); break; case 2: pscr_ret__ = stem##2(variable); break; case 4: pscr_ret__ = stem##4(variable); break; case 8: pscr_ret__ = stem##8(variable); break; default: __bad_size_call_parameter(); break; } pscr_ret__; }) #define raw_cpu_read_1(pcp) raw_cpu_generic_read(pcp)#define raw_cpu_generic_read(pcp) ({ *raw_cpu_ptr(&(pcp)); })

這部分是更高層次的宏定義,將##粘貼的函數再次定義為一個宏函數

#define raw_cpu_read(pcp) __pcpu_size_call_return(raw_cpu_read_, pcp) #define __this_cpu_read(pcp) ({ __this_cpu_preempt_check("read"); raw_cpu_read(pcp); })

最后面進行執行__this_cpu_read(current_kprobe);

int __kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs){ struct kprobe *p p = __this_cpu_read(current_kprobe);p=get_kprobe((unsignedlong*)addr);... 省略多行代碼 if (p->break_handler && p->break_handler(p, regs)) { setup_singlestep(p, regs); kcb->kprobe_status = KPROBE_HIT_SS; return 1;}

C++中我們也可以將做成一個指針列表,對應好每個函數的名稱后,再次調用該定義的宏參數,就實現了指針調用。

#define AddFunc(Func) FuncPtrTemplate Func##Map(int mode_name, int state_name) { static auto modeMap = Func##Register(); auto pair = std::make_pair(mode_name, state_name); auto mapEntry = modeMap->find(pair); if (mapEntry == modeMap->end()) return nullptr; return mapEntry->second; } bool Mode::Func(State *state) { auto state_id = getStateId(); auto p_function = Func##Map(getId(), state_id); if (p_function) return p_function(this, state); return false; }AddFunc(IsExit); intmain(){ IsExit(p.get());}

這也是Linux內核中的代碼,用來print不同狀態的打印信息,如果大家想要快速掌握這些使用方法,建議大家擼一擼Linux內核源碼呢。

這就是我分享的#define的操作方法,里面代碼是實踐過的,如果大家有什么更好的思路,歡迎分享交流哈。

責任編輯:xj

原文標題:用宏##粘貼函數,然后用函數指針查找執行的操作

文章出處:【微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 函數
    +關注

    關注

    3

    文章

    4329

    瀏覽量

    62576
  • 指針
    +關注

    關注

    1

    文章

    480

    瀏覽量

    70553
  • define
    +關注

    關注

    0

    文章

    15

    瀏覽量

    3742

原文標題:用宏##粘貼函數,然后用函數指針查找執行的操作

文章出處:【微信號:strongerHuang,微信公眾號:strongerHuang】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    常用SQL函數及其用法

    SQL(Structured Query Language)是一種用于管理和操作關系數據庫的編程語言。SQL 提供了豐富的函數庫,用于數據檢索、數據更新、數據刪除以及數據聚合等操作。以下是一些常用
    的頭像 發表于 11-19 10:18 ?237次閱讀

    SUMIF函數對比VLOOKUP的優勢

    在Excel中,數據管理和分析是日常工作中不可或缺的一部分。SUMIF函數和VLOOKUP函數是兩個非常受歡迎的函數,它們可以幫助用戶快速地處理和分析數據。盡管它們都可以用于查找和匯總
    的頭像 發表于 11-11 09:16 ?286次閱讀

    SUMIF函數與SUMIFS函數的區別

    SUMIF函數和SUMIFS函數都是Excel中用于條件求和的函數,它們可以幫助用戶根據特定的條件對數據進行求和。盡管它們的基本功能相似,但在使用場景和功能上存在一些差異。以下是對這兩個函數
    的頭像 發表于 10-30 09:51 ?1034次閱讀

    RTOS中鉤子函數的用途及用法

    在很多操作系統中,都存在這樣一類API函數接口:HOOK函數(也叫鉤子函數)。
    的頭像 發表于 10-23 16:25 ?234次閱讀
    RTOS中鉤子<b class='flag-5'>函數</b>的用途及用法

    面試常考+1:函數指針指針函數、數組指針指針數組

    在嵌入式開發領域,函數指針、指針函數、數組指針指針數組是一些非常重要但又容易混淆的概念。理解它
    的頭像 發表于 08-10 08:11 ?836次閱讀
    面試???1:<b class='flag-5'>函數</b><b class='flag-5'>指針</b>與<b class='flag-5'>指針</b><b class='flag-5'>函數</b>、數組<b class='flag-5'>指針</b>與<b class='flag-5'>指針</b>數組

    TC387中有__disable_interrupts()關閉所有中斷和打開所有中斷的函數嗎?

    TC387 芯片中有__disable_irq()和__enable_irq()關閉所有中斷和打開所有中斷的函數嗎,請告知
    發表于 08-01 08:22

    C語言函數指針六大應用場景詳解

    函數指針是一種非常強大的編程工具,它可以讓我們以更加靈活的方式編寫程序。在本文中,我們將介紹 6 個函數指針的高級應用場景,并貼出相應的代碼案例和解釋。
    的頭像 發表于 04-23 18:19 ?884次閱讀

    回調函數(callback)是什么?回調函數的實現方法

    回調函數是一種特殊的函數,它作為參數傳遞給另一個函數,并在被調用函數執行完畢后被調用?;卣{函數
    發表于 03-12 11:46 ?2905次閱讀

    函數指針與回調函數的應用實例

    通常我們說的指針變量是指向一個整型、字符型或數組等變量,而函數指針是指向函數函數指針
    的頭像 發表于 03-07 11:13 ?400次閱讀
    <b class='flag-5'>函數</b><b class='flag-5'>指針</b>與回調<b class='flag-5'>函數</b>的應用實例

    嵌入式Linux C語言編程程序調試與定義

    在Linux使用gcc編譯程序的時候,對于調試的語句還具有一些特殊的語法。gcc編譯的過程中,會生成一些,可以使用這些分別打印當前源文件的信息,主要內容是當前的文件、當前運行的函數和當前的程序行。
    發表于 03-01 11:41 ?1002次閱讀

    output函數怎么

    output 函數是一個通用的術語,并不特指某個具體的編程語言或軟件工具。 如果你在使用 Python 編程語言,那么可能是指 print 函數。Python 中的 print 函數用于將指定的內容
    的頭像 發表于 02-23 14:21 ?1248次閱讀

    linuxgdb調試遇到函數調用怎么辦?

    linuxgdb調試遇到函數調用怎么辦? 在Linux上使用GDB調試時,遇到函數調用是一個常見的情況。函數調用可能涉及到多個函數、多個文
    的頭像 發表于 01-31 10:33 ?712次閱讀

    GD32 MCU是如何進入中斷函數

    用過GD32 MCU的小伙伴們都知道,程序是順序執行的,但當有中斷來的時候程序會跳轉到中斷函數,執行完中斷函數后程序又繼續回到原來的位置繼續執行
    的頭像 發表于 01-30 09:45 ?1074次閱讀
    GD32 MCU是如何進入中斷<b class='flag-5'>函數</b>的

    如何用Rust過程魔法簡化SQL函數呢?

    這是 RisingWave 中一個 SQL 函數的實現。只需短短幾行代碼,通過在 Rust 函數上加一行過程,我們就把它包裝成了一個 SQL 函數。
    的頭像 發表于 01-23 09:43 ?946次閱讀
    如何用Rust過程<b class='flag-5'>宏</b>魔法簡化SQL<b class='flag-5'>函數</b>呢?

    函數指針指針函數是不是一個東西?

    函數指針的本質是指針,就跟整型指針、字符指針一樣,函數指針
    的頭像 發表于 01-03 16:35 ?526次閱讀
    <b class='flag-5'>函數</b><b class='flag-5'>指針</b>和<b class='flag-5'>指針</b><b class='flag-5'>函數</b>是不是一個東西?
    主站蜘蛛池模板: 色 花 堂 永久 网站| 国产精品久久久久久免费播放| 国产人妻人伦精品59HHH| 男人扒开添女人下部口述| 欧美14videosex性欧美成人| 帅哥操美女| 国产成人一区二区三区在线观看| 女人精69xxxxx舒心| 97在线观看免费视频| 久久精品视在线-2| 妖精视频在线观看高清| 国产永久免费高清在线观看| 羞羞影院午夜男女爽爽影院网站| 成品片a免人看免费| 色婷婷激情AV精品影院| 白洁在线观看| 跳蛋按摩棒玉势PLAY高H| 国产国拍亚洲精品av麻豆| 推倒美女总裁啪啪| 国产美女影院| 亚洲AV久久无码精品九号软件 | 久久天天婷婷五月俺也去| 亚洲AV中文字幕无码久久| 恋夜影院安卓免费列表uc| 放射源分类办法| 97草碰在线视频免费| 午夜伦理 第1页| 秋霞网在线伦理免费| 就操成人网| 国产自产第一区c国产| 丰满人妻无码AV系列| 中文国产在线观看| 亚洲精品无码久久久久A片| 人和拘一级毛片| 美国一级黄色| 久久青草在线视频精品| 国产区免费在线观看| 冠希和阿娇13分钟在线视频| 97se se| 最近中文字幕在线中文高清版| 亚洲AV国产国产久青草|