函數指針和指針函數的區別


一、【函數指針】  
    在程序運行中,函數代碼是程序的算法指令部分,它們和數組一樣也佔用存儲空間,都有相應的地址。可以使用指針變量指向數組的首地址,也可以使用指針變量指向函數代碼的首地址,指向函數代碼首地址的指針變量稱爲函數指針。 

1、函數指針定義 

顧名思義,函數指針說的就是一個指針,但這個指針指向的函數,不是普通的基本數據類型或者類對象。

函數類型(*指針變量名)(形參列表); 
“函數類型”說明函數的返回類型,由於“()”的優先級高於“*”,所以指針變量名外的括號必不可少,後面的“形參列表”表示指針變量指向的函數所帶的參數列表。 
例如: 
int (*f)(int x); 
double (*ptr)(double x); 在定義函數指針時請注意:      
函數指針和它指向的函數的參數個數和類型都應該是—致的; 函數指針的類型和函數的返回值類型也必須是一致的。 
2、函數指針的賦值 
函數名和數組名一樣代表了函數代碼的首地址
,因此在賦值時,直接將函數指針指向函數名就行了。 例如, 
int func(int x);   /* 聲明一個函數 */ 
int (*f) (int x);    /* 聲明一個函數指針 */ 
f=func;            /* 將func函數的首地址賦給指針f */ 
賦值時函數func不帶括號,也不帶參數,由於func代表函數的首地址,因此經過賦值以後,指針f就指向函數func(x)的代碼的首地址。 
3、通過函數指針調用函數 
函數指針是通過函數名及有關參數進行調用的。 
與其他指針變量相類似,如果指針變量pi是指向某整型變量i的指針,則*p等於它所指的變量i;如果pf是指向某浮點型變量f的指針,則*pf就等價於它所指的變量f。同樣地,*f是指向函數func(x)的指針,則*f就代表它所指向的函數func。所以在執行了f=func;之後,(*f)和func代表同一函數。 
由於函數指針指向存儲區中的某個函數,因此可以通過函數指針調用相應的函數。現在我們就討論如何用函數指針調用函數,它應執行下面三步: 首先,要說明函數指針變量。
例如:int (*f)(int x); 
其次,要對函數指針變量賦值。 
例如: f=func;    (func(x)必須先要有定義) 
最後,要用 (*指針變量)(參數表);調用函數。 
例如:    (*f)(x);(x必須先賦值) 
【例】任意輸入n個數,找出其中最大數,並且輸出最大數值。 
main() 

    int f();         
    int i,a,b; 
    int (*p)();    /* 定義函數指針 */         
    scanf("%d",&a); 
    p=f;            /* 給函數指針p賦值,使它指向函數f */         
    for(i=1;i<9;i++)        
    { 
        scanf("%d",&b); 
        a=(*p)(a,b);    /* 通過指針p調用函數f */        
    }
printf("The Max Number is:%d",a) 

 
f(int x,int y) 
{    
    int z;    
    z=(x>y)?x:y;  
    return(z); 

運行結果爲: 
343 -45 4389 4235 1 -534 988 555 789↙ The Max Number is:4389 

 

函數指針,首先它是一個指針,只是這個指針指向的是一個函數。指針變量可以指向變量的地址、數組、字符串、動態分配地址,同時也可指向一個函數,每個函數在編譯的時候,系統會分配給該函數一個入口地址,函數名錶示這個入口地址,那麼指向函數的指針變量稱爲函數指針變量。

在編寫嵌入式驅動的時候,會遇到下面的結構體:

struct file_operations {

int (*seek) (struct inode * ,struct file *, off_t ,int);

int (*read) (struct inode * ,struct file *, char ,int);

int (*write) (struct inode * ,struct file *, off_t ,int);

int (*readdir) (struct inode * ,struct file *, struct dirent * ,int);

int (*select) (struct inode * ,struct file *, int ,select_table *);

int (*ioctl) (struct inode * ,struct file *, unsined int ,unsigned long);

int (*mmap) (struct inode * ,struct file *, struct vm_area_struct *);

int (*open) (struct inode * ,struct file *);

int (*release) (struct inode * ,struct file *);

int (*fsync) (struct inode * ,struct file *);

int (*fasync) (struct inode * ,struct file *,int);

int (*check_media_change) (struct inode * ,struct file *);

int (*revalidate) (dev_t dev);

}

上面這個結構體file_operations裏面的組件都是函數指針:int (*read) (struct inode * ,struct file *, char ,int);注意int (*read)是加上括號的。


二、【指針函數】 
一個函數不僅可以帶回一個整型數據的值,字符類型值和實型類型的值,還可以帶回指針類型的數據,使其指向某個地址單元。 
       返回指針的函數,一般定義格式爲:         
       類型標識符    *函數名(參數表)
        int *f(x,y); 

其中x,y是形式參數,f是函數名,調用後返回一個指向整型數據的地址指針。f(x,y)是函數,其值是指針。 

注意,此函數有返回值,返回值爲int *,即返回值是指針類型的。

如:char *ch();表示的就是一個返回字符型指針的函數,請看下面的例題: 
【例】將字符串1(str1)複製到字符串2(str2),並輸出字符串2. 
#include "stdio.h"
 main() 
{
    char *ch(char *,char *); 
    char str1[]="I am glad to meet you!";     
    char str2[]="Welcom to study C!";     
    printf("%s",ch(str1,str2)); 

char *ch(char *str1,char *str2) 
{    
    int i;     
char *p;     
p=str2      
if(*str2==NULL) exit(-1);     
do     
{  
*str2=*str1;   
str1++;  
str2++; 
}
while(*str1!=NULL);     
return(p); 

通過分析可得: 
函數指針是一個指向函數的指針,而指針函數只是說明他是一個返回值爲指針的函數, 函數指針可以用來指向一個函數。
發佈了191 篇原創文章 · 獲贊 363 · 訪問量 124萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章