天天看點

函數指針的探索函數指針

函數指針--指向函數的指針

  • 函數指針
    • 函數指針的概念
    • 函數指針的用法
      • 函數指針的聲明
      • 函數指針作為參數傳入函數
      • 完整程式

函數指針

函數指針的概念

在描述函數指針之前,我想先講講函數的概念。

試想這樣一種場景,你在一個程式中編寫了一個函數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;
}
           

繼續閱讀