學習了數組之后,我們知道數組是在內存中申請一塊內存空間;數組名代表內存塊的首地址,通過數組名可以訪問內存塊中的數據。
寧江網站制作公司哪家好,找成都創(chuàng)新互聯公司!從網頁設計、網站建設、微信開發(fā)、APP開發(fā)、響應式網站等網站項目制作,到程序開發(fā),運營維護。成都創(chuàng)新互聯公司于2013年創(chuàng)立到現在10年的時間,我們擁有了豐富的建站經驗和運維經驗,來保證我們的工作的順利進行。專注于網站建設就選成都創(chuàng)新互聯公司。
那么,對于函數,它也是存放在內存塊中的一段數據。例如下面的函數:
void func( int a )
{
printf( "in func, a = %d " , a );
}
此時,定義了一個函數名是func的函數。可以如下調用該函數:
func(100);
此時,就進入了func函數的函數體中執(zhí)行。可以看到, 函數名如同數組名一樣,代表函數所在內存塊的首地址 。通過數組名可以訪問數組在內存塊中申請的內存,同理,通過函數名,可以訪問函數在內存中存放的數據。
所以,函數名就代表了該函數在內存塊中存放的首地址。那么,函數名是表示一個地址,就可以把這個地址值存放在某一個指針變量中,然后,通過指針變量訪問函數名指向的函數。
在C語言中,提供了函數指針變量,可以存放函數名表示的地址。函數指針變量的定義格式如下:
返回數據類型 (*函數指針變量名)(形參列表)
對比函數的定義如下:
返回數據類型 函數名(形參列表)
可以看到,函數指針變量的定義,與函數的定義格式基本一樣,唯一的區(qū)別是把“函數名”轉換為“*(函數指針變量名)”;總結如下:
(1) 使用指針降級運算符*來定義,表示這個是一個指針。
(2) 指針降級運算符*不可以靠近返回數據類型,例如“返回數據類*”就表示函數的返回類型是一個指針。那么,為了讓指針降級運算符*能夠修飾函數指針變量,就用小括號()把指針降級運算符*與函數指針變量名包含起來。
定義了函數指針變量之后,可以把函數名賦給函數指針變量。因為,函數名就表示函數在內存塊中的首地址,所以,可以直接把一個地址賦值給函數指針變量。格式如下:
函數指針變量 = 函數名;
最終,可以通過函數指針變量調用函數,調用的格式與通過函數名調用完全一樣,通過函數指針變量調用函數,有如下形式:
方法1:函數指針變量(實參列表);
方法2:(*函數指針變量名)(實參列表);
很多情況下,我們更傾向于使用第一種形式,因為,它的使用方式更接近于通過函數名調用函數。
下面根據程序測試例子來看看怎么樣應用函數指針變量。
深入學習,可以交個朋友,工人人人號:韋凱峰linux編程學堂
程序運行結果如下:
深入學習,可以交個朋友,工人人人號:韋凱峰linux編程學堂
可以看到,我們定義了func函數和函數指針變量pfunc,然后,把函數名func設置給函數指針變量pfunc,最終,通過函數指針變量pfunc調用函數。
因為函數指針變量存放的就是函數名表示的地址,所以,函數指針變量與函數名一樣,可以直接通過函數指針變量調用函數。
注意:我們在學習指針的時候,可以把一個int類型的變量地址賦值給int類型的指針;但是,不可以把int類型變量的地址,賦值給double類型的指針。這就是變量數據類型不一致的問題。
同樣的道理,定義函數的時候,函數的返回數據類型和形參列表都不一樣,所以,函數指針變量能夠接收的函數名,它們定義的 函數返回數據類型和形參列表必須一致 ,此時,就如同變量與指針變量類型一致時,才可以把變量的地址賦值給指針變量一樣。
如下是一個測試例子:
深入學習,可以交個朋友,工人人人號:韋凱峰linux編程學堂
程序編譯結果如下:
深入學習,可以交個朋友,工人人人號:韋凱峰linux編程學堂
可以看到,我們把func函數的形參列表修改為double,但是,函數指針變量pfunc定義的形參列表為int類型,此時,函數和函數指針變量的定義格式不一致,所以,不可以把函數名表示的地址設置給函數指針變量。我們來總結一下:
(1) 在Ubuntu系統(tǒng)中,使用GCC編譯,提示warning警告,但是,程序可以編譯通過,可以運行。
(2) 在Windows系統(tǒng)中,使用Visual Studio工具,無法編譯該代碼,提示類型不一致。
(3) 從代碼的嚴謹方面來說,是不可以設置類型不一致的數據。所以,我們應該編寫嚴謹的代碼,函數定義的類型,與函數指針類型不一致的時候,不可以把函數名,賦值給函數指針變量。
函數指針變量的定義很重要,我們需要牢記和理解它們使用的方式。下面多舉幾個例子說明函數指針變量的定義和使用。
int func( void );
int (*pfunc)( void );
pfunc = func;
此時,定義func函數,它的返回值類型是int類型,形參列表是void,那么,定義pfunc函數指針變量的時候,它的返回值類型與形參列表都必須與func一樣。
char * func1( int x, int y, int x);
char * (*pfunc1)( int , int , int );
pfunc1 = func1;
char * (*pfunc1)( int x, int y, int x);
我們再總結一下:
(1) 函數名表示函數在內存塊中的首地址,可以直接把函數名賦值給函數指針變量;
(2) 定義函數指針變量的時候,函數返回數據類型和形參列表必須與要指向函數的定義一致;
#includestring.h??//?導入頭文件string.h
#includestdio.h???//?導入頭文件stdio.h
char?*fun(char?*t)??//?定義函數,?名稱fun,?輸入參數為char?*,?返回值為char?*
{
char?*p?=?t;????//?把t的值賦值給p,?相當于p指向與t相同的字符串
return?p?+?strlen(t)?/?2;???//?strlen返回值為字符串長度,?然后p位移其一半(向下取整)的距離并返回值
}
int?main(int?argc,?char?*argv[])
{
char?*str?=?"abcdefgh";?//?str指向字符串“abcdefgh”
str?=?fun(str);?????????//?str調用fun函數,?參數為str,?并將返回值賦值給str
puts(str);??????????????//?此時str指向e,?輸出為“efgh\n”
return?0;
}
C語言中,使用typedef 定義一個函數指針類型的書寫格式如下:
typedef? 返回值類型?? (*函數指針類型名稱)(參數列表);
為方便理解,下面在手機上使用易歷知食軟件內部的微C程序設計來編程,演示其定義方式,并寫個測試函數,再通過函數指針來調用測試函數,在手機上的代碼如下圖(圖截取自手機):
運行結果如下圖:
在最上面加一句這樣的定義
typedef void*(*pFn)();
pFn可以這樣理解:首先pFn是一個指針,指針指向一個函數(或者說pFn是一個函數指針),此函數返回一個無類型的指針。最終定義的變量及函數都是指針罷了,不過是指針的類型不同。所以在編譯時會有警告,說指針類型不匹配。但對于程序來講,都是可以在特定的上下文中使用的。
運行結果是
t1,t2交替出現。
其實void也可以換為其它的類型如int, double等
又想到一個很好的辦法:
這次編譯不會有警告,運行也不會出錯。
示例代碼如下所示
#include stdio.h
long t1();
long t2();
int main()
{
long(*fn)()= (long (*)()) t1 ;
while(1){
fn = (long (*)()) fn();
}
}
long t1()
{
printf("t1\n");
return (long)t2 ;
}
long t2()
{
printf("t2\n");
return (long)t1 ;
}
01
指針函數通常是指函數返回值是指針的一類函數,如圖所示。
02
函數指針是指指向某個具體函數的指針變量,在程序設計時可以用來調用某個特定函數或者做某個函數的參數。其形式一般如圖:
03
指針函數與函數指針本質上的區(qū)別是,指針函數是一個帶指針的函數,總的來說還是一個函數,如圖就是一個帶*name指針的函數
04
函數指針是指向函數的指針變量,本質上還是一個指針,其格式如下,可以看到和指針函數的格式非常像,所以一定要用心留意。
函數指針是指向函數的指針變量。 因而“函數指針”本身首先應是指針變量,只不過該指針變量指向函數。這正如用指針變量可指向整型變量、字符型、數組一樣,這里是指向函數。
int func(int x); /* 聲明一個函數 */
int (*f) (int x); /* 聲明一個函數指針 */
f=func; /* 將func函數的首地址賦給指針f */
賦值時函數func不帶括號,也不帶參數,由于func代表函數的首地址,因此經過賦值以后,指針f就指向函數func(x)的代碼的首地址。
注2:函數括號中的形參可有可無,視情況而定。
下面的程序說明了函數指針調用函數的方法:
例一、
#includestdio.h
int max(int x,int y){ return(xy?x:y); }
void main()
{
int (*ptr)(int, int);
int a,b,c;
ptr=max;
scanf("%d%d",a,b);
c=(*ptr)(a,b);
printf("a=%d,b=%d,max=%d",a,b,c);
}
ptr是指向函數的指針變量,所以可把函數max()賦給ptr作為ptr的值,即把max()的入口地址賦給ptr,以后就可以用ptr來調用該函數,實際上ptr和max都指向同一個入口地址,不同就是ptr是一個指針變量,不像函數名稱那樣是死的,它可以指向任何函數,就看你想怎么做了。在程序中把哪個函數的地址賦給它,它就指向哪個函數。而后用指針變量調用它,因此可以先后指向不同的函數。不過注意,指向函數的指針變量沒有++和--運算,用時要小心。
指針函數是指返回值是指針的函數,即本質是一個函數。我們知道函數都有返回類型(如果不返回值,則為無值型),只不過指針函數返回類型是某一類型的指針。
其定義格式如下所示:
返回類型標識符*返回名稱(形式參數表)
{ 函數體}
返回類型可以是任何基本類型和復合類型。返回指針的函數的用途十分廣泛。事實上,每一個函數,即使它不帶有返回某種類型的指針,它本身都有一個入口地址,該地址相當于一個指針。比如函數返回一個整型值,實際上也相當于返回一個指針變量的值,不過這時的變量是函數本身而已,而整個函數相當于一個“變量”。
其實還是指針,只是指向的內容和聲明方法不同而已
網頁名稱:c語言定義指針函數格式 c語言 指針函數
分享路徑:http://vcdvsql.cn/article42/doscohc.html
成都網站建設公司_創(chuàng)新互聯,為您提供網站改版、用戶體驗、網站內鏈、、動態(tài)網站、小程序開發(fā)
聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯