當前位置:首頁 » 編程語言 » c語言指針函數教學
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

c語言指針函數教學

發布時間: 2023-03-02 06:35:17

c語言中指針怎麼使用

1、使用場景

使用指針時,必須將它指向一個變數的地址或者為它分配空間方能使用,如下所示:

#include<stdio.h>

#include <stdlib.h>

int main(int argc, char const *argv[])

{

int a[5]={0,1,2,3,4};

int *b,*d;

int c=2;

int *e=a; //e指向a數組首地址

//*b=2; 無法直接初始化

//printf("%d ", *b);

e=e+2; //移動兩個地址單元

d=&c; //d指向c的地址來表示值

c=4; //修改原c變數的值,d指針的值會發生改變

b=(int *)malloc(sizeof(int));//為b分配一個int型空間來直接存儲

*b=2;//分配空間後可以直接賦值了

printf("this is e,b,c,d :%d %d %d %d ",*e,*b,c,*d);

2、類型說明

(1)int *a :表示一個指向int型變數的指針,指向的是變數的地址單元

(2)char *b:表示一個指向char變數的指針

*a表示的是這個指針指向地址的值,a為此指針本身的地址,這點要明確,一般用*(a+1)、*(a+2)來表示值,如:

int nums[5]={0,1,2,3,4};

int *a=nums;

printf("%d %d %p ",*a,*(a+1),a);

(1)c語言指針函數教學擴展閱讀:

指針的運算

指針指向變數地址,若原變數的內容發生了變化,它本身也會發生變化,指針之間的運算一般為值運算和地址運算

(1)值運算:直接通過*運算方式,像a+*(a+1),結果為第一個元素與第二個元素相加。

int nums[5]={0,1,2,3,4};

int *a=nums;

(2)地址運算:通過a+i的方式.指針會指向a的下i個地址。

int nums[5]={0,1,2,3,4};

int *a=nums;

a=a+2;

printf("%d ",*a);

結果輸出2。

參考資料來源 :指針-網路

⑵ C語言指針函數

char *match (char*s,char ch1,char ch2)
函數各部分的含義:
第一個char,一般是代表函數的返回值是一個字元。但是它後面有一個*,應該把char和*連起來看,就是char*了。
那麼,第一個就是char*,代表函數的返回值是一個字元指針(地址)。
match是函數的名字。
括弧內是函數的參數,多個參數用逗號分隔。本例共有3個參數:char*s,char ch1,char ch2,第一個是s,類型為char*型(字元指針型),後兩個ch1、ch2都是char型(字元型)。

到這兒,你就知道去掉*match前的*為什麼就不對了。
另外,括弧里參數類型(如包含指針)跟函數返回值的類型無關。函數名前加不加*只與函數返回值的類型有關。

⑶ C語言中函數指針用法

函數在內存中有一個物理位置,而這個位置是可以賦給一個指針的。一零點函數的地址就是該函數的入口點。因此,函數指針可被用來調用一個函數。函數的地址是用不帶任何括弧或參數的函數名來得到的。(這很類似於數組地址的得到方法,即,在只有數組名而無下標是就得到數組地址。)

怎樣說明一個函數指針變數呢 ?

為了說明一個變數 fn_pointer 的類型是"返回值為 int 的函數指針", 你可以使用下面的說明語句:

int (*fn_pointer) ();

為了讓編譯器能正確地解釋這句語句, *fn_pointer 必須用括弧圍起來。若漏了這對括弧, 則:

int *fn_pointer ();

的意思完全不同了。fn_pointer 將是一個函數名, 其返回值為 int 類型的指針。

2:函數指針變數

在C語言中規定,一個函數總是佔用一段連續的內存區, 而函數名就是該函數所佔內存區的首地址。 我們可以把函數的這個首地址 ( 或稱入口地址 ) 賦予一個指針變數, 使該指針變數指向該函數。然後通過指針變數就可以找到並調用這個函數。我們把這種指向函數的指針變數稱為 " 函數指針變數 " 。

函數指針變數定義的一般形式為:

類型說明符 (* 指針變數名 )();

其中 " 類型說明符 " 表示被指函數的返回值的類型。 "(* 指針變數名 )" 表示 "*" 後面的變數是定義的指針變數。 最後的空括弧表示指針變數所指的是一個函數。

例如: int (*pf)();

表示 pf 是一個指向函數入口的指針變數,該函數的返回值 ( 函數值 ) 是整型。

下面通過例子來說明用指針形式實現對函數調用的方法。

int max(int a,int b)

{

if(a>b)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);

}

從上述程序可以看出用,函數指針變數形式調用函數的步驟如下:

1>. 先定義函數指針變數,如後一程序中第 9 行 int (*pmax)(); 定義 pmax 為函數指針變數。

2>. 把被調函數的入口地址 ( 函數名 ) 賦予該函數指針變數,如程序中第 11 行 pmax=max;

3>. 用函數指針變數形式調用函數,如程序第 14 行 z=(*pmax)(x,y); 調用函數的一般形式為: (* 指針變數名 ) ( 實參表 ) 使用函數指針變數還應注意以下兩點:

a. 函數指針變數不能進行算術運算,這是與數組指針變數不同的。數組指針變數加減一個整數可使指針移動指向後面或前面的數組元素,而函數指針的移動是毫無意義的。

b. 函數調用中 "(* 指針變數名 )" 的兩邊的括弧不可少,其中的 * 不應該理解為求值運算,在此處它只是一種表示符號。

3:指針型函數

前面我們介紹過,所謂函數類型是指函數返回值的類型。 在C語言中允許一個函數的返回值是一個指針 ( 即地址 ) ,這種返回指針值的函數稱為指針型函數。

定義指針型函數的一般形式為:

類型說明符 * 函數名 ( 形參表 )

{

…… /* 函數體 */

}

其中函數名之前加了 "*" 號表明這是一個指針型函數,即返回值是一個指針。類型說明符表示了返回的指針值所指向的數據類型。

如:

int *ap(int x,int y)

{

…… /* 函數體 */

}

表示 ap 是一個返回指針值的指針型函數, 它返回的指針指向一個整型變數。下例中定義了一個指針型函數 day_name ,它的返回值指向一個字元串。該函數中定義了一個靜態指針數組 name 。 name 數組初始化賦值為八個字元串,分別表示各個星期名及出錯提示。形參 n 表示與星期名所對應的整數。在主函數中, 把輸入的整數 i 作為實參, 在 printf 語句中調用 day_name 函數並把 i 值傳送給形參 n 。 day_name 函數中的 return 語句包含一個條件表達式, n 值若大於 7 或小於 1 則把 name[0] 指針返回主函數輸出出錯提示字元串 "Illegal day" 。否則返回主函數輸出對應的星期名。主函數中的第 7 行是個條件語句,其語義是,如輸入為負數 (i<0) 則中止程序運行退出程序。 exit 是一個庫函數, exit(1) 表示發生錯誤後退出程序, exit(0) 表示正常退出。

應該特別注意的是函數指針變數和指針型函數這兩者在寫法和意義上的區別。如 int(*p)() 和 int *p() 是兩個完全不同的量。 int(*p)() 是一個變數說明,說明 p 是一個指向函數入口的指針變數,該函數的返回值是整型量, (*p) 的兩邊的括弧不能少。

int *p() 則不是變數說明而是函數說明,說明 p 是一個指針型函數,其返回值是一個指向整型量的指針,*p 兩邊沒有括弧。作為函數說明, 在括弧內最好寫入形式參數,這樣便於與變數說明區別。 對於指針型函數定義,int *p() 只是函數頭部分,一般還應該有函數體部分。

main()

{

int i;

char *day_name(int n);

printf("input Day No:/n");

scanf("%d",&i);

if(i<0) 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((n<1||n>7) ? name[0] : name[n]);

}

本程序是通過指針函數,輸入一個 1 ~ 7 之間的整數, 輸出對應的星期名。指針數組的說明與使用一個數組的元素值為指針則是指針數組。指針數組是一組有序的指針的集合。指針數組的所有元素都必須是具有相同存儲類型和指向相同數據類型的指針變數。

指針數組說明的一般形式為: 類型說明符 * 數組名 [ 數組長度 ]

其中類型說明符為指針值所指向的變數的類型。例如: int *pa[3] 表示 pa 是一個指針數組,它有三個數組元素, 每個元素值都是一個指針,指向整型變數。通常可用一個指針數組來指向一個二維數組。 指針數組中的每個元素被賦予二維數組每一行的首地址,因此也可理解為指向一個一維數組。圖 6—6 表示了這種關系。

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;i<3;i++)

printf("%d,%d,%d/n",a[i][2-i],*a[i],*(*(a+i)+i));

for(i=0;i<3;i++)

printf("%d,%d,%d/n",*pa[i],p[i],*(p+i));

}

本常式序中, pa 是一個指針數組,三個元素分別指向二維數組 a 的各行。然後用循環語句輸出指定的數組元素。其中 *a[i] 表示 i 行 0 列元素值; *(*(a+i)+i) 表示 i 行 i 列的元素值; *pa[i] 表示 i 行 0 列元素值;由於 p 與 a[0] 相同,故 p[i] 表示 0 行 i 列的值; *(p+i) 表示 0 行 i 列的值。讀者可仔細領會元素值的各種不同的表示方法。 應該注意指針數組和二維數組指針變數的區別。 這兩者雖然都可用來表示二維數組,但是其表示方法和意義是不同的

⑷ c語言指針簡單教程

指針是C語言中廣泛使用的一種數據類型。 運用指針編程是C語言最主要的風格之一。利用指針變數可以表示各種數據結構; 能很方便地使用數組和字元串; 並能象匯編語言一樣處理內存地址,從而編出精練而高效的程序。指針極大地豐富了C語言的功能。 學習指針是學習C語言中最重要的一環, 能否正確理解和使用指針是我們是否掌握C語言的一個標志。同時, 指針也是C語言中最為困難的一部分,在學習中除了要正確理解基本概念,還必須要多編程,上機調試。只要作到這些,指針也是不難掌握的。

指針的基本概念 在計算機中,所有的數據都是存放在存儲器中的。 一般把存儲器中的一個位元組稱為一個內存單元, 不同的數據類型所佔用的內存單元數不等,如整型量佔2個單元,字元量佔1個單元等, 在第二章中已有詳細的介紹。為了正確地訪問這些內存單元, 必須為每個內存單元編上號。 根據一個內存單元的編號即可准確地找到該內存單元。內存單元的編號也叫做地址。 既然根據內存單元的編號或地址就可以找到所需的內存單元,所以通常也把這個地址稱為指針。 內存單元的指針和內存單元的內容是兩個不同的概念。 可以用一個通俗的例子來說明它們之間的關系。我們到銀行去存取款時, 銀行工作人員將根據我們的帳號去找我們的存款單, 找到之後在存單上寫入存款、取款的金額。在這里,帳號就是存單的指針, 存款數是存單的內容。對於一個內存單元來說,單元的地址即為指針, 其中存放的數據才是該單元的內容。在C語言中, 允許用一個變數來存放指針,這種變數稱為指針變數。因此, 一個指針變數的值就是某個內存單元的地址或稱為某內存單元的指針。圖中,設有字元變數C,其內容為「K」(ASCII碼為十進制數 75),C佔用了011A號單元(地址用十六進數表示)。設有指針變數P,內容為011A, 這種情況我們稱為P指向變數C,或說P是指向變數C的指針。 嚴格地說,一個指針是一個地址, 是一個常量。而一個指針變數卻可以被賦予不同的指針值,是變。 但在常把指針變數簡稱為指針。為了避免混淆,我們中約定:「指針」是指地址, 是常量,「指針變數」是指取值為地址的變數。 定義指針的目的是為了通過指針去訪問內存單元。

既然指針變數的值是一個地址, 那麼這個地址不僅可以是變數的地址, 也可以是其它數據結構的地址。在一個指針變數中存放一
個數組或一個函數的首地址有何意義呢? 因為數組或函數都是連續存放的。通過訪問指針變數取得了數組或函數的首地址, 也就找到了該數組或函數。這樣一來, 凡是出現數組,函數的地方都可以用一個指針變數來表示, 只要該指針變數中賦予數組或函數的首地址即可。這樣做, 將會使程序的概念十分清楚,程序本身也精練,高效。在C語言中, 一種數據類型或數據結構往往都佔有一組連續的內存單元。 用「地址」這個概念並不能很好地描述一種數據類型或數據結構, 而「指針」雖然實際上也是一個地址,但它卻是一個數據結構的首地址, 它是「指向」一個數據結構的,因而概念更為清楚,表示更為明確。 這也是引入「指針」概念的一個重要原因。

指針變數的類型說明

對指針變數的類型說明包括三個內容:
(1)指針類型說明,即定義變數為一個指針變數;
(2)指針變數名;
(3)變數值(指針)所指向的變數的數據類型。
其一般形式為: 類型說明符 *變數名;
其中,*表示這是一個指針變數,變數名即為定義的指針變數名,類型說明符表示本指針變數所指向的變數的數據類型。
例如: int *p1;表示p1是一個指針變數,它的值是某個整型變數的地址。 或者說p1指向一個整型變數。至於p1究竟指向哪一個整型變數, 應由向p1賦予的地址來決定。
再如:
staic int *p2; /*p2是指向靜態整型變數的指針變數*/
float *p3; /*p3是指向浮點變數的指針變數*/
char *p4; /*p4是指向字元變數的指針變數*/ 應該注意的是,一個指針變數只能指向同類型的變數,如P3 只能指向浮點變數,不能時而指向一個浮點變數, 時而又指向一個字元變數。

指針變數的賦值

指針變數同普通變數一樣,使用之前不僅要定義說明, 而且必須賦予具體的值。未經賦值的指針變數不能使用, 否則將造成系統混亂,甚至死機。指針變數的賦值只能賦予地址, 決不能賦予任何其它數據,否則將引起錯誤。在C語言中, 變數的地址是由編譯系統分配的,對用戶完全透明,用戶不知道變數的具體地址。 C語言中提供了地址運算符&來表示變數的地址。其一般形式為: & 變數名; 如&a變示變數a的地址,&b表示變數b的地址。 變數本身必須預先說明。設有指向整型變數的指針變數p,如要把整型變數a 的地址賦予p可以有以下兩種方式:
(1)指針變數初始化的方法 int a;
int *p=&a;
(2)賦值語句的方法 int a;
int *p;
p=&a;
不允許把一個數賦予指針變數,故下面的賦值是錯誤的: int *p;p=1000; 被賦值的指針變數前不能再加「*」說明符,如寫為*p=&a 也是錯誤的

指針變數的運算

指針變數可以進行某些運算,但其運算的種類是有限的。 它只能進行賦值運算和部分算術運算及關系運算。
1.指針運算符

(1)取地址運算符&
取地址運算符&是單目運算符,其結合性為自右至左,其功能是取變數的地址。在scanf函數及前面介紹指針變數賦值中,我們已經了解並使用了&運算符。

(2)取內容運算符*
取內容運算符*是單目運算符,其結合性為自右至左,用來表示指針變數所指的變數。在*運算符之後跟的變數必須是指針變數。需要注意的是指針運算符*和指針變數說明中的指針說明符* 不是一回事。在指針變數說明中,「*」是類型說明符,表示其後的變數是指針類型。而表達式中出現的「*」則是一個運算符用以表示指針變數所指的變數。
main(){
int a=5,*p=&a;
printf ("%d",*p);
}
......
表示指針變數p取得了整型變數a的地址。本語句表示輸出變數a的值。
2.指針變數的運算

(1)賦值運算

指針變數的賦值運算有以下幾種形式:
①指針變數初始化賦值,前面已作介紹。

②把一個變數的地址賦予指向相同數據類型的指針變數。例如:
int a,*pa;
pa=&a; /*把整型變數a的地址賦予整型指針變數pa*/

③把一個指針變數的值賦予指向相同類型變數的另一個指針變數。如:
int a,*pa=&a,*pb;
pb=pa; /*把a的地址賦予指針變數pb*/
由於pa,pb均為指向整型變數的指針變數,因此可以相互賦值。

④把數組的首地址賦予指向數組的指針變數。
例如: int a[5],*pa;
pa=a; (數組名表示數組的首地址,故可賦予指向數組的指針變數pa)
也可寫為:
pa=&a[0]; /*數組第一個元素的地址也是整個數組的首地址,
也可賦予pa*/
當然也可採取初始化賦值的方法:
int a[5],*pa=a;

⑤把字元串的首地址賦予指向字元類型的指針變數。例如: char *pc;pc="c language";或用初始化賦值的方法寫為: char *pc="C Language"; 這里應說明的是並不是把整個字元串裝入指針變數, 而是把存放該字元串的字元數組的首地址裝入指針變數。 在後面還將詳細介紹。

⑥把函數的入口地址賦予指向函數的指針變數。例如: int (*pf)();pf=f; /*f為函數名*/

(2)加減算術運算

對於指向數組的指針變數,可以加上或減去一個整數n。設pa是指向數組a的指針變數,則pa+n,pa-n,pa++,++pa,pa--,--pa 運算都是合法的。指針變數加或減一個整數n的意義是把指針指向的當前位置(指向某數組元素)向前或向後移動n個位置。應該注意,數組指針變數向前或向後移動一個位置和地址加1或減1 在概念上是不同的。因為數組可以有不同的類型, 各種類型的數組元素所佔的位元組長度是不同的。如指針變數加1,即向後移動1 個位置表示指針變數指向下一個數據元素的首地址。而不是在原地址基礎上加1。
例如:
int a[5],*pa;
pa=a; /*pa指向數組a,也是指向a[0]*/
pa=pa+2; /*pa指向a[2],即pa的值為&pa[2]*/ 指針變數的加減運算只能對數組指針變數進行, 對指向其它類型變數的指針變數作加減運算是毫無意義的。(3)兩個指針變數之間的運算只有指向同一數組的兩個指針變數之間才能進行運算, 否則運算毫無意義。

①兩指針變數相減
兩指針變數相減所得之差是兩個指針所指數組元素之間相差的元素個數。實際上是兩個指針值(地址) 相減之差再除以該數組元素的長度(位元組數)。例如pf1和pf2 是指向同一浮點數組的兩個指針變數,設pf1的值為2010H,pf2的值為2000H,而浮點數組每個元素佔4個位元組,所以pf1-pf2的結果為(2000H-2010H)/4=4,表示pf1和 pf2之間相差4個元素。兩個指針變數不能進行加法運算。 例如, pf1+pf2是什麼意思呢?毫無實際意義。

②兩指針變數進行關系運算
指向同一數組的兩指針變數進行關系運算可表示它們所指數組元素之間的關系。例如:
pf1==pf2表示pf1和pf2指向同一數組元素
pf1>pf2表示pf1處於高地址位置
pf1<pf2表示pf2處於低地址位置
main(){
int a=10,b=20,s,t,*pa,*pb;
pa=&a;
pb=&b;
s=*pa+*pb;
t=*pa**pb;
printf("a=%d\nb=%d\na+b=%d\na*b=%d\n",a,b,a+b,a*b);
printf("s=%d\nt=%d\n",s,t);
}
......
說明pa,pb為整型指針變數
給指針變數pa賦值,pa指向變數a。
給指針變數pb賦值,pb指向變數b。
本行的意義是求a+b之和,(*pa就是a,*pb就是b)。
本行是求a*b之積。
輸出結果。
輸出結果。
......
指針變數還可以與0比較。設p為指針變數,則p==0表明p是空指針,它不指向任何變數;p!=0表示p不是空指針。空指針是由對指針變數賦予0值而得到的。例如: #define NULL 0int *p=NULL; 對指針變數賦0值和不賦值是不同的。指針變數未賦值時,可以是任意值,是不能使用的。否則將造成意外錯誤。而指針變數賦0值後,則可以使用,只是它不指向具體的變數而已。
main(){
int a,b,c,*pmax,*pmin;
printf("input three numbers:\n");
scanf("%d%d%d",&a,&b,&c);
if(a>b){
pmax=&a;
pmin=&b;}
else{
pmax=&b;
pmin=&a;}
if(c>*pmax) pmax=&c;
if(c<*pmin) pmin=&c;
printf("max=%d\nmin=%d\n",*pmax,*pmin);
}
......
pmax,pmin為整型指針變數。
輸入提示。
輸入三個數字。
如果第一個數字大於第二個數字...
指針變數賦值
指針變數賦值

指針變數賦值
指針變數賦值
判斷並賦值
判斷並賦值
輸出結果
......

⑸ C語言函數指針怎麼用

有函數: int fun(int a,int b);
要定義指向該函數的指針
對比指向 int a; 的指針
int *p; p = &a;
p的定義是怎麼來的?
首先要保證p是一個指針類型
寫下(*p),
然後,考慮下p的基類型,
p的基類型就是變數a的類型int
將int 放在(*p)前面就行了
int (*p);
括弧可以省略,就成了 int *p;

同理
想要實現 pf = &fun;
(*pf) 將pf定義為一個指針,
將fun的類型作為pf的基類型
fun相當於一個 int (int a,int b)類型的量
int (int a,int b) (*pf);
基類型中有圓括弧和中括弧要後移
int (*pf)(int a,int b) ;//括弧不能省略
pf = &fun;
調用時
(*pf)(3,4); pf(3,4)都可以

⑹ C語言編如何寫指針函數

1
#include<iostream>
using namespace;
void main()
{
int a=0,b=0;
int *s=a;int *p=b;
cout<<「please the two numbers」;
cin>>a;
cin>>b;
int fun(int *a,int *b)
{
if(*a==*b)
{
cout<<"different\n";return 1;
else cout<<"same\n"; return 0;
}
fun(s,p);
}

include<iostream>
using namespace std;
void main()
{
int a[10]={0};
int i=0,j=0,k=0,p=0,m=0;
int *x=a;int *n=a;
for(;i<=9;++i)
{
cout<<"input the "<<i+1<<"number(s)";
cin>>a[i];
}
int fun(int *a)
{
for(;*x!=null;++x)
for(;m<=9;++m)
{
if(*x<a[m]) break;
n=x;
}
cout<<"the max is"<<*n;
}

⑺ C語言指針函數和函數指針詳細介紹

  • 01

    指針函數通常是指函數返回值是指針的一類函數,如圖所示。

  • 02

    函數指針是指指向某個具體函數的指針變數,在程序設計時可以用來調用某個特定函數或者做某個函數的參數。其形式一般如圖:

  • 03

    指針函數與函數指針本質上的區別是,指針函數是一個帶指針的函數,總的來說還是一個函數,如圖就是一個帶*name指針的函數

  • 04

    函數指針是指向函數的指針變數,本質上還是一個指針,其格式如下,可以看到和指針函數的格式非常像,所以一定要用心留意。

⑻ C語言函數指針,敲黑白,講重點,如何定義函數指針

學習了數組之後,我們知道數組是在內存中申請一塊內存空間;數組名代表內存塊的首地址,通過數組名可以訪問內存塊中的數據。

那麼,對於函數,它也是存放在內存塊中的一段數據。例如下面的函數:

void func( int a )

{

printf( "in func, a = %d " , a );

}

此時,定義了一個函數名是func的函數。可以如下調用該函數:

func(100);

此時,就進入了func函數的函數體中執行。可以看到, 函數名如同數組名一樣,代表函數所在內存塊的首地址 。通過數組名可以訪問數組在內存塊中申請的內存,同理,通過函數名,可以訪問函數在內存中存放的數據。

所以,函數名就代表了該函數在內存塊中存放的首地址。那麼,函數名是表示一個地址,就可以把這個地址值存放在某一個指針變數中,然後,通過指針變數訪問函數名指向的函數。

在C語言中,提供了函數指針變數,可以存放函數名表示的地址。函數指針變數的定義格式如下:

返回數據類型 (*函數指針變數名)(形參列表)

對比函數的定義如下:

返回數據類型 函數名(形參列表)

可以看到,函數指針變數的定義,與函數的定義格式基本一樣,唯一的區別是把「函數名」轉換為「*(函數指針變數名)」;總結如下:

(1) 使用指針降級運算符*來定義,表示這個是一個指針。

(2) 指針降級運算符*不可以靠近返回數據類型,例如「返回數據類*」就表示函數的返回類型是一個指針。那麼,為了讓指針降級運算符*能夠修飾函數指針變數,就用小括弧()把指針降級運算符*與函數指針變數名包含起來。

定義了函數指針變數之後,可以把函數名賦給函數指針變數。因為,函數名就表示函數在內存塊中的首地址,所以,可以直接把一個地址賦值給函數指針變數。格式如下:

函數指針變數 = 函數名;

最終,可以通過函數指針變數調用函數,調用的格式與通過函數名調用完全一樣,通過函數指針變數調用函數,有如下形式:

方法1:函數指針變數(實參列表);

方法2:(*函數指針變數名)(實參列表);

很多情況下,我們更傾向於使用第一種形式,因為,它的使用方式更接近於通過函數名調用函數。

下面根據程序測試例子來看看怎麼樣應用函數指針變數。

深入學習,可以交個朋友,工人人人號:韋凱峰linux編程學堂

程序運行結果如下:

深入學習,可以交個朋友,工人人人號:韋凱峰linux編程學堂

可以看到,我們定義了func函數和函數指針變數pfunc,然後,把函數名func設置給函數指針變數pfunc,最終,通過函數指針變數pfunc調用函數。

因為函數指針變數存放的就是函數名表示的地址,所以,函數指針變數與函數名一樣,可以直接通過函數指針變數調用函數。

注意:我們在學習指針的時候,可以把一個int類型的變數地址賦值給int類型的指針;但是,不可以把int類型變數的地址,賦值給double類型的指針。這就是變數數據類型不一致的問題。

同樣的道理,定義函數的時候,函數的返回數據類型和形參列表都不一樣,所以,函數指針變數能夠接收的函數名,它們定義的 函數返回數據類型和形參列表必須一致 ,此時,就如同變數與指針變數類型一致時,才可以把變數的地址賦值給指針變數一樣。

如下是一個測試例子:

深入學習,可以交個朋友,工人人人號:韋凱峰linux編程學堂

程序編譯結果如下:

深入學習,可以交個朋友,工人人人號:韋凱峰linux編程學堂

可以看到,我們把func函數的形參列表修改為double,但是,函數指針變數pfunc定義的形參列表為int類型,此時,函數和函數指針變數的定義格式不一致,所以,不可以把函數名表示的地址設置給函數指針變數。我們來總結一下:

(1) 在Ubuntu系統中,使用GCC編譯,提示warning警告,但是,程序可以編譯通過,可以運行。

(2) 在Windows系統中,使用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) 定義函數指針變數的時候,函數返回數據類型和形參列表必須與要指向函數的定義一致;