<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          初識 typedef void(*Func)(void)

          共 3501字,需瀏覽 8分鐘

           ·

          2021-05-15 10:36

          關(guān)注、星標(biāo)公眾號,直達(dá)精彩內(nèi)容

          來源:技術(shù)讓夢想更偉大

          作者:李肖遙


          void (*Fun)(void);假如就只是寫上這樣的一句代碼,顯然這就是定義了一個(gè)變量Fun,這個(gè)Fun變量是一個(gè)指針,指向返回值和參數(shù)都是空的函數(shù)的指針。而typedef void(*Func)(void) 是函數(shù)指針的類型定義,代表了一種新的類型。作用是聲明一個(gè) void(*)()類型的函數(shù)指針Func。這些基礎(chǔ)知識我們一步一步來學(xué)習(xí)了解一下。

          typedef/define的基本概念

          typedef

          現(xiàn)有類型創(chuàng)建一個(gè)新的名字,基本用法舉例:

          typedef unsigned char UCHAR;//右邊代替左邊

          typedef能隱藏笨拙的語法構(gòu)造以及平臺一些相關(guān)的數(shù)據(jù)類型,可以使得代碼更美觀,可維護(hù)性、可移植性、可讀性更強(qiáng),來舉個(gè)例子吧。

          //定義一個(gè)函數(shù)
          void tech(void) { printf("tech dreamer"); }
          void main()
          {
              //定義一個(gè)指針,指針的名字叫func
              void (*func)();//tech函數(shù)帶參數(shù)的話也可以
              func = &tech; //&可以不加
              func();        //第一種調(diào)用方式,帶參數(shù)也可以
              (*func)();     //第二種調(diào)用方式,帶參數(shù)也可以
          }

          為了寫出更加美觀和可讀性強(qiáng)的代碼,我們經(jīng)常使用typedef來定義一個(gè)類型,代碼如下。

          void tech(void) { printf("tech dreamer"); }
          //命名一個(gè)類型,那么這個(gè)時(shí)候func不可以直接調(diào)用,而是一個(gè)類型了
          typedef void (*func)();
          void main()
          {
              //定義一個(gè)可調(diào)用的指針變量(函數(shù)):myfunc
              func myfunc;
              myfunc = &tech; //&可以不加
              myfunc();         //第一種調(diào)用方式,帶參數(shù)也可以
              (*myfunc)();      //第二種調(diào)用方式,帶參數(shù)也可以
          }

          與define的區(qū)別

          typedef 是在編譯過程中被解析的,而#define是在編譯之前的預(yù)處理時(shí)被破解的;#define只是對所定義的別名的簡單替換,而typedef可以做到#define能做到的所有事情,而且可以做得更好

          函數(shù)指針的基本概念

          我們先了解一下函數(shù)指針的基本概念,函數(shù)指針是指向函數(shù)的指針變量,他的本質(zhì)是一個(gè)指針變量,函數(shù)的指針定義:int (*f)(int);

          //舉個(gè)例子聲明一個(gè)函數(shù)指針
          int (*f)(int x);
          f=func; /* 將func函數(shù)的首地址賦給指針f */

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

          指針函數(shù)是返回值是某一類型指針的函數(shù),即本質(zhì)是一個(gè)函數(shù),指針函數(shù)定義:int *fun(int x);,舉個(gè)例子如下

          float *fun();  
          float *p;  
          p = fun(a);  

          這個(gè)函數(shù)的返回值是一個(gè)地址值,賦值給用同類型的指針變量p,也就是說,指針函數(shù)一定有函數(shù)返回值,而且在主調(diào)函數(shù)中,函數(shù)返回值必須賦給同類型的指針變量。

          兩者主要的區(qū)別是一個(gè)是指針變量,一個(gè)是函數(shù)。

          typedef void(*Func)(void)為什么能這么用?

          可能我們有這樣的疑問,typedef一般的用法不是取個(gè)新名字嗎?如果仿照變量類型聲明,應(yīng)該是這樣typedef void(*)()  variable;才比較眼熟易懂。

          說一說我的理解,我們知道C語言的函數(shù)在被調(diào)用的時(shí)候是執(zhí)行了一條轉(zhuǎn)移指令,這條指令包含要轉(zhuǎn)移到的地方的數(shù)據(jù),同理,變量代表了一個(gè)地址,當(dāng)你引用一個(gè)變量的時(shí)候,計(jì)算機(jī)會把這個(gè)地址的數(shù)據(jù)拿出來參與運(yùn)算。

          那么函數(shù)名也是一樣,函數(shù)名代表的是一段代碼的入口地址,引用了這個(gè)函數(shù),那么計(jì)算機(jī)會使用轉(zhuǎn)移指令轉(zhuǎn)移到函數(shù)名代表的地址。

          所以typedef void(*Func)(void)相當(dāng)于定義了一種類型,這個(gè)類型具有下面的特征:他是一個(gè)函數(shù),沒有返回值,沒有參數(shù)。

          因?yàn)樘幚砥髟谶M(jìn)行上下文切換或者轉(zhuǎn)移的時(shí)候要進(jìn)行現(xiàn)場保護(hù),不同的函數(shù)對現(xiàn)場保護(hù)的內(nèi)容可能不一樣,傳入的參數(shù)使用的棧也不一樣,相同類型的函數(shù)保證了現(xiàn)場保護(hù)的內(nèi)容是一樣的,參數(shù)的形式也是一樣的。所以這樣使用可以像用指針引用數(shù)據(jù)一樣使用函數(shù)。

          typedef void(*Func)(void)的應(yīng)用

          用法的好處,定義一個(gè)函數(shù)指針類型。

          例子:

          上面說到typedef void(*Func)(void)可以使得代碼更可移植性、可讀性更強(qiáng),我們舉個(gè)例子,有三個(gè)類型相似或功能相似的函數(shù):

          //構(gòu)造3個(gè)通用函數(shù)
          void TEST1(void) { printf("test1\n"); }//函數(shù)定義  
          void TEST2(void) { printf("test2\n"); }//函數(shù)定義  
          void TEST3(void) { printf("test3\n"); }//函數(shù)定義  
          ... ...  
          //聲明  
          typdef void (*func)(void);

          再來定義一個(gè)調(diào)用的函數(shù)

          void test(int i)  
          {  
            func vTask[3] = {&TEST1, &TEST2, &TEST3};  
            func fun = vTask[i];  
            (*fun)();  
          }  

          在main函數(shù)中,分別調(diào)用這幾個(gè)不同輸入?yún)?shù)的函數(shù)

          void main()
          {
            test(0);
            test(1);
            test(2);
           return 0;
          }

          這樣的話代碼就看著很舒服了。

          參考:https://blog.csdn.net/flyztek/article/details/73610255

          ????????????????  END  ????????????????

          推薦閱讀:


          嵌入式編程專輯
          Linux 學(xué)習(xí)專輯
          C/C++編程專輯
          Qt進(jìn)階學(xué)習(xí)專輯

          關(guān)注我的微信公眾號,回復(fù)“加群”按規(guī)則加入技術(shù)交流群。


          點(diǎn)擊“閱讀原文”查看更多分享。

          瀏覽 61
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲 国产 色在线 | 特级黄色录相片 | www.17草 | 九九九无码视频 | 人人射在线观看 |