免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
深入理解C語言中的函數(shù)聲明

 輸入理解C語言中的函數(shù)聲明收藏

看了C陷阱與缺陷,第一個給我震撼的就是理解函數(shù)聲明了,下面是我的理解。

1.理解函數(shù)聲明
    為了模擬開機啟動時的情形,我們必須設計出一個C語句,以顯示調(diào)用位于地址0的子例程。調(diào)用語句如下:
    (*(void (*)())0)();
膽顫了吧?首先我們從函數(shù)的聲明說起:有如下一個函數(shù)
    void func(){...}
那么,要想聲明一個函數(shù)指針,指向這類函數(shù),怎樣聲明呢?如下:
    void (*pf)();
那么,想要將一個值轉(zhuǎn)換成一個指針,指向這類函數(shù),怎么強制轉(zhuǎn)換呢?如下:
    (void (*)())value
現(xiàn)在value被轉(zhuǎn)換成了一個指向函數(shù)的指針,怎么調(diào)用它呢?如下:
    ((void) (*)()value)();
或    (*(void) (*)()value)();
或    (******(void) (*)value)();
神奇吧,看了上面的函數(shù)調(diào)用方式!其實你完全可以這樣調(diào)用函數(shù):
    func();
    (*func)();
    (********func)();
沒有任何問題!

    對于初學的時候,最容易頭暈的就是指針符*到底是什么東西?它是變量的一部分?還是聲明類型的一部分?其實,仔細回憶C中標識符的定義規(guī)則就知道,指針符*必須是類型聲明的一部分,因為變量的聲明不能含有指針符號,否則是一個非法的變量!
    
2.C語言中的聲明
對比簡單類型的強制轉(zhuǎn)換我們就可以更加明白上面的強制轉(zhuǎn)換,簡單類型定義如下:
    int a;
    char b;
    b=(char)a;
    int *a;
    char *b;
    b=(int *)a;
    其實,在各種指針之間轉(zhuǎn)換很少見,最常見的就是將void指針轉(zhuǎn)換成各種指針,用過malloc族函數(shù)嗎?
    a=(int *)malloc(sizeof(int));
由于聲明符和表達式類似,所以你可以這樣聲明
    int ((a));    //將a聲明為一個int型值
    int *func(),(*fp)();    
    前者是一個函數(shù),后者是一個指針,所以千萬不要對指針定義成函數(shù)了,分不清概念的時候最容易這樣
    int (*fp)(){
        /*do something*/
    }
顯然,這里將一個指針定義成了一個函數(shù)!這是任何編譯器都不能容忍的。
    結合簡單變量的類型,出去聲明中的變量,得到的就是這個變量的類型,如float a,那么要將一個變量轉(zhuǎn)換成a的類型,那么只需要
(float)value;即可,同理:
float *b,除去變量b,得到b的類型是(float *)。
float (*fp)();除去變量fp,得到的類型是float (*)(),所以要將變量轉(zhuǎn)換成fp類型的值時,只需要(float (*)())value,即可!這樣value即被轉(zhuǎn)換成一個函數(shù)指針了,也就像最前面的例子中那樣!
如果,更復雜,有聲明如下:
float * (*fp)();    //返回一個float指針
其實,這也是唬人的,同理可知:強制轉(zhuǎn)換類型為(float * (*)())value;

3.其他考量
    看到第一個例子時,可能想,能不能這樣子:(*0)();呢?
不行,因為0是一個數(shù)字,而*必須要操作一個指針,而且對于要調(diào)用的函數(shù)是void型的,所以這個指針應該轉(zhuǎn)換成相應的類型,所以需要將0轉(zhuǎn)成一個指向void返回值的參數(shù)為空的函數(shù)的指針。
    最后,linux內(nèi)核中的信號處理函數(shù)定義如下:
void (*signal(int,void (*)(int)))(int);
首先,將上面的函數(shù)聲明看成這樣void (*p)(int);可知,p是一個函數(shù),所以signal函數(shù)的返回類型為一個函數(shù)指針,指向的函數(shù)類型是
void (*)(int);使用typedef可以簡化上面signal函數(shù)的聲明
typedef void (*HANDLER)(int);
HANDLER signal(int,HANDLER);
解釋一下:signal是一個返回函數(shù)指針的函數(shù),返回的指針指向的函數(shù)類型是void (*)(int);而signal的參數(shù)一個是int,另一個是一個函數(shù),類型為void (*)(int),剛好就是最初聲明的樣子。




[轉(zhuǎn)]理解C語言函數(shù)聲明(摘自C陷阱和缺陷)



摘自C陷阱和缺陷一書,但被網(wǎng)上一個自認為是高手的挫人改成這個樣子,湊合著看吧

聲明與函數(shù) 有一段程序存儲在起始地址為0的一段內(nèi)存上,如果我們想要調(diào)用這段程序,請問該如何去做?   

答案 答案是(*(void (*)( ) )0)( )??雌饋泶_實令人頭大,那好,讓我們知難而上,從兩個不同的途徑來詳細分析這個問題。   

答案分析:從尾到頭   

首先,最基本的函數(shù)聲明:void function (paramList); 最基本的函數(shù)調(diào)用:function(paramList); 鑒于問題中的函數(shù)沒有參數(shù),函數(shù)調(diào)用可簡化為 function();   

其次,根據(jù)問題描述,可以知道0是這個函數(shù)的入口地址,也就是說,0是一個函數(shù)的指針。使用函數(shù)指針的函數(shù)聲明形式是:void (*pFunction)(),相應的調(diào)用形式是: (*pFunction)(),則問題中的函數(shù)調(diào)用可以寫作:(*0)( )。  

第三,大家知道,函數(shù)指針變量不能是一個常數(shù),因此上式中的0必須要被轉(zhuǎn)化為函數(shù)指針。我們先來研究一下,對于使用函數(shù)指針的函數(shù):比如void(*pFunction)( ),函數(shù)指針變量的原型是什么? 這個問題很簡單,pFunction函數(shù)指針原型是( void (*)( )),即去掉變量名,清晰起見,整個加上()號。所以將0強制轉(zhuǎn)換為一個返回值為void,參數(shù)為空的函數(shù)指針如下:( void (*)( ) )。OK,結合2)和3)的分析,結果出來了,那就是:(*(void (*)( ) )0)( ) 。   

答案分析:從頭到尾理解答案   

(void (*)( )) ,是一個返回值為void,參數(shù)為空的函數(shù)指針原型.(void (*)())0,把0轉(zhuǎn)變成一個返回值為void,參數(shù)為空的函數(shù)指針,指針指向的地址為0.   *(void (*)())0,前面加上*表示整個是一個返回值為void的函數(shù)的名字  (*(void (*)( ))0)( ),這當然就是一個函數(shù)了。我們可以使用typedef清晰聲明如下:   typedef void (*pFun)( ); 這樣函數(shù)變?yōu)?(*(pFun)0 )( );

問題:三個聲明的分析  對聲明進行分析,最根本的方法還是類比替換法,從那些最基本的聲明上進行類比,簡化,從而進行理解,下面通過分析三個例子,來具體闡述如何使用這種方法。

#1:int* (*a[5])(int, char*);   

首先看到標識符名a,"[]"優(yōu)先級大于"*",a與"[5]"先結合。所以a是一個數(shù)組,這個數(shù)組有5個元素,每一個元素都是一個指針,指針指向"(int, char*)",很明顯,指向的是一個函數(shù),這個函數(shù)參數(shù)是"int, char*",返回值是"int*"。OK,結束了一個。:)

#2:void (*b[10]) (void (*)());   

 b是一個數(shù)組,這個數(shù)組有10個元素,每一個元素都是一個指針,指針指向一個函數(shù),函數(shù)參數(shù)是"void (*)()"【注10】,返回值是"void"。完畢!   注意:這個參數(shù)又是一個指針,指向一個函數(shù),函數(shù)參數(shù)為空,返回值是"void"。

#3. double(*)() (*pa)[9];    pa是一個指針,指針指向一個數(shù)組,這個數(shù)組有9個元素,每一個元素都是"double(*)()"(也即一個函數(shù)指針,指向一個函數(shù),這個函數(shù)的參數(shù)為空,返回值是"double")。

(自己注:#3看起來有點難理解,如果把double(*)()換成int, 變成int (*pa)[9]這樣就不難理解了)

本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
C語言結構體指針變量作函數(shù)參數(shù)
[原創(chuàng)] 程序員面試寶典:第七章 指針與引用
C語言和C 的區(qū)別到底有多少?不要再傻傻分不清楚了
void 型指針的高階用法,你掌握了嗎?
typedef void (*Fun) (void) 的理解
15W4K58S4 實驗3:空指針與位變量
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服