學(xué)習(xí)了數(shù)組之后,我們知道數(shù)組是在內(nèi)存中申請(qǐng)一塊內(nèi)存空間;數(shù)組名代表內(nèi)存塊的首地址,通過數(shù)組名可以訪問內(nèi)存塊中的數(shù)據(jù)。
成都創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比公安網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式公安網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋公安地區(qū)。費(fèi)用合理售后完善,十多年實(shí)體公司更值得信賴。
那么,對(duì)于函數(shù),它也是存放在內(nèi)存塊中的一段數(shù)據(jù)。例如下面的函數(shù):
void func( int a )
{
printf( "in func, a = %d " , a );
}
此時(shí),定義了一個(gè)函數(shù)名是func的函數(shù)??梢匀缦抡{(diào)用該函數(shù):
func(100);
此時(shí),就進(jìn)入了func函數(shù)的函數(shù)體中執(zhí)行。可以看到, 函數(shù)名如同數(shù)組名一樣,代表函數(shù)所在內(nèi)存塊的首地址 。通過數(shù)組名可以訪問數(shù)組在內(nèi)存塊中申請(qǐng)的內(nèi)存,同理,通過函數(shù)名,可以訪問函數(shù)在內(nèi)存中存放的數(shù)據(jù)。
所以,函數(shù)名就代表了該函數(shù)在內(nèi)存塊中存放的首地址。那么,函數(shù)名是表示一個(gè)地址,就可以把這個(gè)地址值存放在某一個(gè)指針變量中,然后,通過指針變量訪問函數(shù)名指向的函數(shù)。
在C語言中,提供了函數(shù)指針變量,可以存放函數(shù)名表示的地址。函數(shù)指針變量的定義格式如下:
返回?cái)?shù)據(jù)類型 (*函數(shù)指針變量名)(形參列表)
對(duì)比函數(shù)的定義如下:
返回?cái)?shù)據(jù)類型 函數(shù)名(形參列表)
可以看到,函數(shù)指針變量的定義,與函數(shù)的定義格式基本一樣,唯一的區(qū)別是把“函數(shù)名”轉(zhuǎn)換為“*(函數(shù)指針變量名)”;總結(jié)如下:
(1) 使用指針降級(jí)運(yùn)算符*來定義,表示這個(gè)是一個(gè)指針。
(2) 指針降級(jí)運(yùn)算符*不可以靠近返回?cái)?shù)據(jù)類型,例如“返回?cái)?shù)據(jù)類*”就表示函數(shù)的返回類型是一個(gè)指針。那么,為了讓指針降級(jí)運(yùn)算符*能夠修飾函數(shù)指針變量,就用小括號(hào)()把指針降級(jí)運(yùn)算符*與函數(shù)指針變量名包含起來。
定義了函數(shù)指針變量之后,可以把函數(shù)名賦給函數(shù)指針變量。因?yàn)椋瘮?shù)名就表示函數(shù)在內(nèi)存塊中的首地址,所以,可以直接把一個(gè)地址賦值給函數(shù)指針變量。格式如下:
函數(shù)指針變量 = 函數(shù)名;
最終,可以通過函數(shù)指針變量調(diào)用函數(shù),調(diào)用的格式與通過函數(shù)名調(diào)用完全一樣,通過函數(shù)指針變量調(diào)用函數(shù),有如下形式:
方法1:函數(shù)指針變量(實(shí)參列表);
方法2:(*函數(shù)指針變量名)(實(shí)參列表);
很多情況下,我們更傾向于使用第一種形式,因?yàn)椋氖褂梅绞礁咏谕ㄟ^函數(shù)名調(diào)用函數(shù)。
下面根據(jù)程序測(cè)試?yán)觼砜纯丛趺礃討?yīng)用函數(shù)指針變量。
深入學(xué)習(xí),可以交個(gè)朋友,工人人人號(hào):韋凱峰linux編程學(xué)堂
程序運(yùn)行結(jié)果如下:
深入學(xué)習(xí),可以交個(gè)朋友,工人人人號(hào):韋凱峰linux編程學(xué)堂
可以看到,我們定義了func函數(shù)和函數(shù)指針變量pfunc,然后,把函數(shù)名func設(shè)置給函數(shù)指針變量pfunc,最終,通過函數(shù)指針變量pfunc調(diào)用函數(shù)。
因?yàn)楹瘮?shù)指針變量存放的就是函數(shù)名表示的地址,所以,函數(shù)指針變量與函數(shù)名一樣,可以直接通過函數(shù)指針變量調(diào)用函數(shù)。
注意:我們?cè)趯W(xué)習(xí)指針的時(shí)候,可以把一個(gè)int類型的變量地址賦值給int類型的指針;但是,不可以把int類型變量的地址,賦值給double類型的指針。這就是變量數(shù)據(jù)類型不一致的問題。
同樣的道理,定義函數(shù)的時(shí)候,函數(shù)的返回?cái)?shù)據(jù)類型和形參列表都不一樣,所以,函數(shù)指針變量能夠接收的函數(shù)名,它們定義的 函數(shù)返回?cái)?shù)據(jù)類型和形參列表必須一致 ,此時(shí),就如同變量與指針變量類型一致時(shí),才可以把變量的地址賦值給指針變量一樣。
如下是一個(gè)測(cè)試?yán)樱?/p>
深入學(xué)習(xí),可以交個(gè)朋友,工人人人號(hào):韋凱峰linux編程學(xué)堂
程序編譯結(jié)果如下:
深入學(xué)習(xí),可以交個(gè)朋友,工人人人號(hào):韋凱峰linux編程學(xué)堂
可以看到,我們把func函數(shù)的形參列表修改為double,但是,函數(shù)指針變量pfunc定義的形參列表為int類型,此時(shí),函數(shù)和函數(shù)指針變量的定義格式不一致,所以,不可以把函數(shù)名表示的地址設(shè)置給函數(shù)指針變量。我們來總結(jié)一下:
(1) 在Ubuntu系統(tǒng)中,使用GCC編譯,提示warning警告,但是,程序可以編譯通過,可以運(yùn)行。
(2) 在Windows系統(tǒng)中,使用Visual Studio工具,無法編譯該代碼,提示類型不一致。
(3) 從代碼的嚴(yán)謹(jǐn)方面來說,是不可以設(shè)置類型不一致的數(shù)據(jù)。所以,我們應(yīng)該編寫嚴(yán)謹(jǐn)?shù)拇a,函數(shù)定義的類型,與函數(shù)指針類型不一致的時(shí)候,不可以把函數(shù)名,賦值給函數(shù)指針變量。
函數(shù)指針變量的定義很重要,我們需要牢記和理解它們使用的方式。下面多舉幾個(gè)例子說明函數(shù)指針變量的定義和使用。
int func( void );
int (*pfunc)( void );
pfunc = func;
此時(shí),定義func函數(shù),它的返回值類型是int類型,形參列表是void,那么,定義pfunc函數(shù)指針變量的時(shí)候,它的返回值類型與形參列表都必須與func一樣。
char * func1( int x, int y, int x);
char * (*pfunc1)( int , int , int );
pfunc1 = func1;
char * (*pfunc1)( int x, int y, int x);
我們?cè)倏偨Y(jié)一下:
(1) 函數(shù)名表示函數(shù)在內(nèi)存塊中的首地址,可以直接把函數(shù)名賦值給函數(shù)指針變量;
(2) 定義函數(shù)指針變量的時(shí)候,函數(shù)返回?cái)?shù)據(jù)類型和形參列表必須與要指向函數(shù)的定義一致;
函數(shù)在內(nèi)存中有一個(gè)物理位置,而這個(gè)位置是可以賦給一個(gè)指針的。一零點(diǎn)函數(shù)的地址就是該函數(shù)的入口點(diǎn)。因此,函數(shù)指針可被用來調(diào)用一個(gè)函數(shù)。函數(shù)的地址是用不帶任何括號(hào)或參數(shù)的函數(shù)名來得到的。(這很類似于數(shù)組地址的得到方法,即,在只有數(shù)組名而無下標(biāo)是就得到數(shù)組地址。)
怎樣說明一個(gè)函數(shù)指針變量呢 ?
為了說明一個(gè)變量 fn_pointer 的類型是"返回值為 int 的函數(shù)指針", 你可以使用下面的說明語句:
int (*fn_pointer) ();
為了讓編譯器能正確地解釋這句語句, *fn_pointer 必須用括號(hào)圍起來。若漏了這對(duì)括號(hào), 則:
int *fn_pointer ();
的意思完全不同了。fn_pointer 將是一個(gè)函數(shù)名, 其返回值為 int 類型的指針。
2:函數(shù)指針變量
在C語言中規(guī)定,一個(gè)函數(shù)總是占用一段連續(xù)的內(nèi)存區(qū), 而函數(shù)名就是該函數(shù)所占內(nèi)存區(qū)的首地址。 我們可以把函數(shù)的這個(gè)首地址 ( 或稱入口地址 ) 賦予一個(gè)指針變量, 使該指針變量指向該函數(shù)。然后通過指針變量就可以找到并調(diào)用這個(gè)函數(shù)。我們把這種指向函數(shù)的指針變量稱為 " 函數(shù)指針變量 " 。
函數(shù)指針變量定義的一般形式為:
類型說明符 (* 指針變量名 )();
其中 " 類型說明符 " 表示被指函數(shù)的返回值的類型。 "(* 指針變量名 )" 表示 "*" 后面的變量是定義的指針變量。 最后的空括號(hào)表示指針變量所指的是一個(gè)函數(shù)。
例如: int (*pf)();
表示 pf 是一個(gè)指向函數(shù)入口的指針變量,該函數(shù)的返回值 ( 函數(shù)值 ) 是整型。
下面通過例子來說明用指針形式實(shí)現(xiàn)對(duì)函數(shù)調(diào)用的方法。
int max(int a,int b)
{
if(ab)return a;
else return b;
}
main()
{
int max(int a,int b);
int(*pmax)();
int x,y,z;
pmax=max;
printf("input two numbers:/n");
scanf("%d%d",x,y);
z=(*pmax)(x,y);
printf("maxmum=%d",z);
}
從上述程序可以看出用,函數(shù)指針變量形式調(diào)用函數(shù)的步驟如下:
1. 先定義函數(shù)指針變量,如后一程序中第 9 行 int (*pmax)(); 定義 pmax 為函數(shù)指針變量。
2. 把被調(diào)函數(shù)的入口地址 ( 函數(shù)名 ) 賦予該函數(shù)指針變量,如程序中第 11 行 pmax=max;
3. 用函數(shù)指針變量形式調(diào)用函數(shù),如程序第 14 行 z=(*pmax)(x,y); 調(diào)用函數(shù)的一般形式為: (* 指針變量名 ) ( 實(shí)參表 ) 使用函數(shù)指針變量還應(yīng)注意以下兩點(diǎn):
a. 函數(shù)指針變量不能進(jìn)行算術(shù)運(yùn)算,這是與數(shù)組指針變量不同的。數(shù)組指針變量加減一個(gè)整數(shù)可使指針移動(dòng)指向后面或前面的數(shù)組元素,而函數(shù)指針的移動(dòng)是毫無意義的。
b. 函數(shù)調(diào)用中 "(* 指針變量名 )" 的兩邊的括號(hào)不可少,其中的 * 不應(yīng)該理解為求值運(yùn)算,在此處它只是一種表示符號(hào)。
3:指針型函數(shù)
前面我們介紹過,所謂函數(shù)類型是指函數(shù)返回值的類型。 在C語言中允許一個(gè)函數(shù)的返回值是一個(gè)指針 ( 即地址 ) ,這種返回指針值的函數(shù)稱為指針型函數(shù)。
定義指針型函數(shù)的一般形式為:
類型說明符 * 函數(shù)名 ( 形參表 )
{
…… /* 函數(shù)體 */
}
其中函數(shù)名之前加了 "*" 號(hào)表明這是一個(gè)指針型函數(shù),即返回值是一個(gè)指針。類型說明符表示了返回的指針值所指向的數(shù)據(jù)類型。
如:
int *ap(int x,int y)
{
…… /* 函數(shù)體 */
}
表示 ap 是一個(gè)返回指針值的指針型函數(shù), 它返回的指針指向一個(gè)整型變量。下例中定義了一個(gè)指針型函數(shù) day_name ,它的返回值指向一個(gè)字符串。該函數(shù)中定義了一個(gè)靜態(tài)指針數(shù)組 name 。 name 數(shù)組初始化賦值為八個(gè)字符串,分別表示各個(gè)星期名及出錯(cuò)提示。形參 n 表示與星期名所對(duì)應(yīng)的整數(shù)。在主函數(shù)中, 把輸入的整數(shù) i 作為實(shí)參, 在 printf 語句中調(diào)用 day_name 函數(shù)并把 i 值傳送給形參 n 。 day_name 函數(shù)中的 return 語句包含一個(gè)條件表達(dá)式, n 值若大于 7 或小于 1 則把 name[0] 指針返回主函數(shù)輸出出錯(cuò)提示字符串 "Illegal day" 。否則返回主函數(shù)輸出對(duì)應(yīng)的星期名。主函數(shù)中的第 7 行是個(gè)條件語句,其語義是,如輸入為負(fù)數(shù) (i0) 則中止程序運(yùn)行退出程序。 exit 是一個(gè)庫函數(shù), exit(1) 表示發(fā)生錯(cuò)誤后退出程序, exit(0) 表示正常退出。
應(yīng)該特別注意的是函數(shù)指針變量和指針型函數(shù)這兩者在寫法和意義上的區(qū)別。如 int(*p)() 和 int *p() 是兩個(gè)完全不同的量。 int(*p)() 是一個(gè)變量說明,說明 p 是一個(gè)指向函數(shù)入口的指針變量,該函數(shù)的返回值是整型量, (*p) 的兩邊的括號(hào)不能少。
int *p() 則不是變量說明而是函數(shù)說明,說明 p 是一個(gè)指針型函數(shù),其返回值是一個(gè)指向整型量的指針,*p 兩邊沒有括號(hào)。作為函數(shù)說明, 在括號(hào)內(nèi)最好寫入形式參數(shù),這樣便于與變量說明區(qū)別。 對(duì)于指針型函數(shù)定義,int *p() 只是函數(shù)頭部分,一般還應(yīng)該有函數(shù)體部分。
main()
{
int i;
char *day_name(int n);
printf("input Day No:/n");
scanf("%d",i);
if(i0) exit(1);
printf("Day No:%2d--%s/n",i,day_name(i));
}
char *day_n
ame(int n)
{
static char *name[]={ "Illegal day",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"};
return((n1||n7) ? name[0] : name[n]);
}
本程序是通過指針函數(shù),輸入一個(gè) 1 ~ 7 之間的整數(shù), 輸出對(duì)應(yīng)的星期名。指針數(shù)組的說明與使用一個(gè)數(shù)組的元素值為指針則是指針數(shù)組。指針數(shù)組是一組有序的指針的集合。指針數(shù)組的所有元素都必須是具有相同存儲(chǔ)類型和指向相同數(shù)據(jù)類型的指針變量。
指針數(shù)組說明的一般形式為: 類型說明符 * 數(shù)組名 [ 數(shù)組長(zhǎng)度 ]
其中類型說明符為指針值所指向的變量的類型。例如: int *pa[3] 表示 pa 是一個(gè)指針數(shù)組,它有三個(gè)數(shù)組元素, 每個(gè)元素值都是一個(gè)指針,指向整型變量。通常可用一個(gè)指針數(shù)組來指向一個(gè)二維數(shù)組。 指針數(shù)組中的每個(gè)元素被賦予二維數(shù)組每一行的首地址,因此也可理解為指向一個(gè)一維數(shù)組。圖 6—6 表示了這種關(guān)系。
int a[3][3]={1,2,3,4,5,6,7,8,9};
int *pa[3]={a[0],a[1],a[2]};
int *p=a[0];
main()
{
int i;
for(i=0;i3;i++)
printf("%d,%d,%d/n",a[i][2-i],*a[i],*(*(a+i)+i));
for(i=0;i3;i++)
printf("%d,%d,%d/n",*pa[i],p[i],*(p+i));
}
本例程序中, pa 是一個(gè)指針數(shù)組,三個(gè)元素分別指向二維數(shù)組 a 的各行。然后用循環(huán)語句輸出指定的數(shù)組元素。其中 *a[i] 表示 i 行 0 列元素值; *(*(a+i)+i) 表示 i 行 i 列的元素值; *pa[i] 表示 i 行 0 列元素值;由于 p 與 a[0] 相同,故 p[i] 表示 0 行 i 列的值; *(p+i) 表示 0 行 i 列的值。讀者可仔細(xì)領(lǐng)會(huì)元素值的各種不同的表示方法。 應(yīng)該注意指針數(shù)組和二維數(shù)組指針變量的區(qū)別。 這兩者雖然都可用來表示二維數(shù)組,但是其表示方法和意義是不同的
#includestdio.h
//定義類型fun_ptr,它是一個(gè)函數(shù)指針,指向的函數(shù)返回值為int,參數(shù)為int
typedef?int?(*fun_ptr)(int);
//fun1
int?fun1(int?a)
{
printf("call?fun1,pram=%d,return?%d+1\n",?a,?a);
return?a+1;
}
//fun2
int?fun2(int?a)
{
printf("call?fun2,pram=%d,return?%d+2\n",?a,?a);
return?a+2;
}
int?main(int?argc,?char?*argv[])
{
int?a?=?10;
int?s?=?0;
//定義函數(shù)指針類型的變量p_fun
fun_ptr?p_fun;
//指向fun1
p_fun?=?fun1;
//執(zhí)行
s=p_fun(a);
printf("s=%d\n",?s);
//指向fun2
p_fun?=?fun2;
//執(zhí)行
s=p_fun(a);
printf("s=%d\n",?s);
return?0;
}
執(zhí)行結(jié)果:
本文名稱:c語言定義與調(diào)用函數(shù)指針 c語言定義指向函數(shù)的指針
URL分享:http://aaarwkj.com/article12/doodpdc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、標(biāo)簽優(yōu)化、建站公司、網(wǎng)頁設(shè)計(jì)公司、域名注冊(cè)、網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)