<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>

          函數(shù)指針,指針函數(shù),函數(shù)指針數(shù)組

          共 2594字,需瀏覽 6分鐘

           ·

          2020-08-20 14:55



          這是一個(gè)群友發(fā)的筆試題目,里面涉及的東西也比較有意思。

          直接看代碼

          void?(*f[])(char?*)

          這個(gè)是個(gè)什么東西?

          我們先看看下面的東西

          函數(shù)指針和指針函數(shù)的定義

          我們看個(gè)代碼

          int?*func(int?a,int?b)

          我們之前說(shuō)過(guò)運(yùn)算符的優(yōu)先級(jí),「 *?」 ?的優(yōu)先級(jí)低于「 ?」

          由于「 * 」的優(yōu)先級(jí)低于「?()?的優(yōu)先級(jí),因而func首先和后面的「 () 」結(jié)合,也就意味著,func是一個(gè)函數(shù)。即:

          int?*(func)(int?a,int?b)

          然后這個(gè)函數(shù)的返回值的類型是? int *? 即:指向int類型的指針

          然后我們這樣修改上面的代碼

          int?(*func)(int?a,int?b)

          (*func) 」說(shuō)明func是一個(gè)指針,然后后面跟著「()」說(shuō)明這個(gè)指針指向一個(gè)函數(shù),即指向函數(shù)的指針。

          所以

          函數(shù)指針:?首先是一個(gè)指針,這個(gè)指針指向一個(gè)函數(shù)

          指針函數(shù):首先是一個(gè)函數(shù),這個(gè)函數(shù)的返回值一個(gè)指針


          用typedef聲明一個(gè)函數(shù)指針

          我們聲明一個(gè)函數(shù)指針,正常方法是

          int?(*pfunc)(int?a,int?b)

          當(dāng)我們命名很多個(gè)函數(shù)指針的時(shí)候,用上面的方法顯得非常不方便,所以我們可以這樣做

          typedef?int?(*PF)?(int?a,intb)
          PF?pfunc;

          例程:

          #include?"stdio.h"

          typedef?int(*PF)(int,?int);

          int?add(int?a,?int?b)
          {
          ?return?a?+?b;
          }

          int?reduce(int?a,?int?b)
          {
          ?return?a?-?b;
          }

          int?main()
          {
          ?PF?pfunc?=?NULL;
          ?pfunc?=?add;
          ?printf("add:%d\n",pfunc(3,?4));
          ?pfunc?=?reduce;
          ?printf("reduce:%d\n",?pfunc(3,?4));
          ?/*getchar是用VS編寫方便查看輸出*/
          ?getchar();
          ?return?0;
          }
          img

          再說(shuō)回上面的那個(gè)題目

          void?(*f[])(char?*)

          f 是個(gè)什么鬼東西了?

          [] 的優(yōu)先級(jí) 比 *的優(yōu)先級(jí)高,所以 f首先是修飾了數(shù)組,然后跟后面的 *組合,就說(shuō)明這個(gè)數(shù)組里面住的都是 指針,這些指針是什么呢,再出來(lái)看看就看到了,這個(gè)指針是 一個(gè)函數(shù),這個(gè)函數(shù)的 參數(shù)是 char *返回值是void

          示例代碼

          #include?

          void?(*f[3])(char?*);

          void?efunction(char?*?s)
          {
          ?printf("%s\n",s);
          }

          int?main()
          {
          ?f[0]?=?efunction;
          ?//void?(*f[])(char?*)?=?{efunction};?
          ?(*f[0])("hello?code");
          ????return?0;
          }

          代碼輸出

          hello?code

          --------------------------------
          Process?exited?after?0.08441?seconds?with?return?value?0
          請(qǐng)按任意鍵繼續(xù).?.?.

          函數(shù)指針在項(xiàng)目總的實(shí)際應(yīng)用

          這是我的android項(xiàng)目hal部分的代碼,這部分代碼用到的是函數(shù)指針,通過(guò)name來(lái)調(diào)用不同的函數(shù)。

          android hal部分代碼

          懂了這些,我們就可以看懂別人的代碼了

          我們有時(shí)候看別人的代碼時(shí)候,經(jīng)常是一面懵逼,比如下面這個(gè)void (*p)(); 還有這個(gè)(*(void(*) ())0)();

          我記得我在以前的文章里面有談到一個(gè)右左原則,從p開始看,往右走直到遇到)再往左走遇到(,(*p)我們就可以看出p是一個(gè)指針,繼續(xù)分析往右走,遇到(),說(shuō)明p指向一個(gè)(void)的函數(shù),往左走,知道p指向的函數(shù)返回值是void

          ok,看下面的例子。

          #include?"stdio.h"

          void?Function()
          {
          ????printf("Call????Function!\n");
          }

          int?main()
          {
          ????void(*p)();
          ????*(int*)&p?=?(int)Function;
          ????(*p)();
          ????getchar();
          ????return?0;
          }
          輸出結(jié)果

          然后繼續(xù)分析(*(void(*) ())0)();

          • 1、void (*)() ?我們上面分析了這個(gè)是一個(gè)函數(shù)指針,只是把p去掉了而已。
          • 2、把上面的void (*)()PN代替,上面的表達(dá)式變成(*(PN)0)();PN后面有一個(gè)0,這個(gè)是讓我們咋舌的地方,然后我們向一下 (char)a;這樣的表達(dá)式,所以*(PN)0就是把0當(dāng)成一個(gè)地址,強(qiáng)制轉(zhuǎn)換為PN類型,用*這個(gè)鑰匙取出這個(gè)地址區(qū)域的值。
          • 3、把(*(PN)0)()替換成PM,原來(lái)的表達(dá)式變成PM(),這樣大家看起來(lái)比較容易了吧,就是正常的函數(shù)調(diào)用。

          給個(gè)例子自己去參透一下

          #include?
          #include?

          char?*?fun1(char?*?p)
          {
          ????printf("%s\n",?p);
          ????return?p;
          }

          char?*?fun2(char?*?p)
          {
          ????printf("%s\n",?p);
          ????return?p;
          }

          char?*?fun3(char?*?p)
          {
          ????printf("%s\n",?p);
          ????return?p;
          }

          int?main()
          {
          ????char?*?(*pf[3])(char?*?p);
          ????pf[0]?=?fun1;?//?可以直接用函數(shù)名
          ????pf[1]?=?&fun2;?//?可以用函數(shù)名加上取地址符
          ????pf[2]?=?&fun3;

          ????pf[0]("fun1");
          ????pf[0]("fun2");
          ????pf[0]("fun3");

          ????getchar();
          ????return?0;
          }


          推薦閱讀:
          ? ??專輯|Linux文章匯總
          ? ??專輯|程序人生
          ? ??專輯|C語(yǔ)言


          嵌入式Linux
          微信掃描二維碼,關(guān)注我的公眾號(hào)?
          瀏覽 52
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

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

          手機(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>
                  色先锋av天天操 少妇 后入 视频 少妇精品一区二区 | 日韩欧美电影一区二区三区 | 三级片中文字幕网 | 欧美激情视频一区二区三区不卡 | 激情综合网五月天 |