函數指針--指向函數的指針
- 函數指針
-
- 函數指針的概念
- 函數指針的用法
-
- 函數指針的聲明
- 函數指針作為參數傳入函數
- 完整程式
函數指針
函數指針的概念
在描述函數指針之前,我想先講講函數的概念。
試想這樣一種場景,你在一個程式中編寫了一個函數f,并且調用了這個函數f,如果對底層比較感興趣的同學,可能會對這個過程中程式發生了什麼有着強烈的好奇心
下面從程式編譯後開始說起
如果對作業系統有了解的同學,可以知道,程式是在使用者程序空間中執行的,一個程式可以看作一個程序。
一個簡化的程序空間模型,可以看作由代碼段,資料段,堆棧三個部分組成(當然還有其餘部分,但我們主要講這三個部分)

代碼段主要存儲整個程式的代碼部分,一般來說是隻讀不可修改的
資料段主要用來存儲整個程式的全局變量或靜态變量
堆棧用來存儲程式的局部變量和用來輔助函數調用
而一個程式編譯之後,我們編寫的函數就被存儲在代碼段。
而這個函數的函數名,就相當于代碼段中這個函數代碼區域的首位址
比如我們編寫了這樣一個函數
void f(){
//process
}
函數名f的含義如圖所示
函數指針的用法
函數指針的聲明
下面看看某個函數的聲明
int func(int n, int m);
然後看看函數指針pfunc的聲明
int (*pfunc)(int n, int m);
令這個函數指針指向函數func
pfunc = &func;
因為函數名本來就表示這個函數的入口位址,是以我們也可以這樣寫
pfunc = func;
最後我們利用函數指針調用函數
(*pfunc)(3,4)
最終傳回結果為7.
函數指針作為參數傳入函數
函數指針主要的用法如下
利用函數指針,我們可以實作一個函數作為另外一個函數的參數,這樣能夠使得我們的函數更加靈活。
要實作一個函數作為另外一個函數的參數,我們可以将函數指針作為函數的參數,聲明如下:
int getRoot(float (*f1)(int n), float (*f2)(int n),int min , int max);
該函數實作了下面一個功能,在[min-max]區間中得到令函數f1(n) >= f2(n)的最接近的整數解,并将該解傳回
該函數的第一個參數即為函數指針f1,該函數指針的聲明為float (*f1)(int n);
第二個參數同樣為函數指針,不過多叙述
講完了函數指針作為一個函數getRoot的參數,接下來看看函數getRoot如何調用這個函數指針所指向的函數。
int getRoot(float (*f1)(int n), float (*f2)(int n),int min , int max){
//search root of equation f1 = f2 from section (min to max)
//precondition There is an integer where f1 is greater than f2
int result = min;
while(result <= max){
if(f1(result) - f2(result) >= 0){
return result;
}
else{
result++;
}
}
return 0;
};
可以看到,我們調用其他函數使用的是這個語句if(f1(result) - f2(result) >= 0),需要調用函數指針指向的函數,隻需要正常使用這個函數就行
完整程式
#include<iostream>
#include<math.h>
//function pointer
using namespace std;
int getRoot(float (*f1)(int n), float (*f2)(int n),int min , int max){
//search root of equation f1 = f2 from section (min to max)
//precondition There is an integer where f1 is greater than f2
int result = min;
while(result <= max){
if(f1(result) - f2(result) >= 0){
return result;
}
else{
result++;
}
}
return 0;
};
float f1(int n){
return n*n;
} //prototype
float f2(int n){
return n + 6;
}
int main(){
//test function pointer
//
float (*pf1)(int n) = &f1;
float (*pf2)(int n) = &f2;
//f1(n):n*n
//f2(n):n+6
int n = getRoot(pf1,pf2,0,8);
cout << n;
//result:n = 3;
}