1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        函數(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開(kāi)始看,往右走直到遇到)再往左走遇到(,(*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)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            欧美乱码精品一区二区三区 | 热re99久久精品国99热线看 | 亚洲日韩欧美久久久 | av女优巨乳 | 草逼毛片 | 日韩精品不卡 | 蜜桃性爱视频 | caobizaixian | 色悠悠一区 | 无app毛片入口 |