1. 程式人生 > >函式指標,轉移表和回撥函式的理解

函式指標,轉移表和回撥函式的理解

函式指標

函式指標顧名思義就是將函式看做一個指標,用一個指標來儲存函式的地址

函式指標的用法:

函式指標的正確寫法是  void (*p1)() 而 void *p2() 是無法存放函式指標的,因為這是返回值為指標的函式,p1先與*結合,說明p1是一個指標,指標指向一個函式,指向的函式無引數,返回值型別為void。具體用法如下例

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
void check(char *a, char *b, int(*cmp)(const char *, const char *))
{
	if ((*cmp)(a, b) == 0)
		//cmp指向庫函式strcmp(),呼叫cmp就是呼叫strcmp(),並且a和b作為引數
		printf("相同\n");
	else
		printf("不相同\n");
}
int main(void)
{
	char arr1[1024], arr2[1024];
	int(*p)(const char *, const char *);
	//將庫函式strcmp的地址賦值給函式指標p
	//並且用限定符const保持呼叫後指標指向內容不變
	p = strcmp;

	printf("請輸入兩個字串,然後進行對比\n");
	scanf("%s", &arr1);
	scanf("%s", &arr2);
	check(arr1, arr2, p);
	return 0;
}

函式指標陣列

函式指標陣列其實就是一組函式指標,兩個的關係就好比如整數和整形陣列,下面是函式指標陣列的正確寫法

int (*p[10])()     p先與[]結合,說明p1是陣列,陣列的內容就是int (*)()型別的函式指標

轉移表

靈性運用轉移表可以讓我們的程式碼有更高的可維護性和可讀性,並減少我們的程式碼量,轉移表我個人理解就是將函式集中轉移到同一個地方,這樣就更加方便我們的閱讀和理解,舉個例子

如果不用轉移表實現一個計算器的功能,我們一般的做法就是定義四個函式int add(int a,int b),int sub(int a,int b),int mul(int a,int b),int div(int a,int b),然後用一個switch語句分別呼叫這四個函式,但是如果我們用轉移表就能減少工作量

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int add(int a, int b){
	return a + b;
}
int sub(int a, int b){
	return a - b;
}
int mul(int a, int b){
	return a * b;
}
int div(int a, int b){
	return a / b;
}
int main(){
	int x, y;
	int choose=1;
	int ret = 0;
	int(*p[5])(int x, int y) = { 0, add, sub, mul, div };
	while (choose){
		printf("請選擇您需要的操作,1:add    2:sub    3:mul    4:div    0:退出\n");
	    scanf("%d", &choose);
		if ((choose <= 4 && choose >= 1)){
			printf("請輸入兩個整數\n");
			scanf("%d %d", &x, &y);
			ret = (*p[choose])(x, y);
		}
		if (choose == 0){
			printf("歡迎下次使用\n");
		}
		else{
			printf("輸入有誤\n");
		}	
		printf("ret=%d\n", ret);
	}
	return 0;
}

回撥函式

回撥函式就是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用來呼叫其所指向的函式時,我們就說這是回撥函式。而且回撥函式還有個特點,那就是回撥函式不是人為的主動呼叫,而是當某個特定時間或者條件發生時由另一方(作業系統或者第三方庫)呼叫,用於對該事件或條件進行響應

下面是具體的例子

int main(){
	printf("hello world");
	return 0;
}//一般的hello world程式

把它改成回撥函式形式

void print_text(){
	printf("hello world");
}//這是回撥函式(被呼叫的函式)

void callback_function(void (*callbackfuct)()){
	callbackfuct();
}//這是實現回撥函式的呼叫函式
//先在形參中定義函式指標,再從main函式中傳入函式的地址
//然後在呼叫函式執行時通過函式指標呼叫回撥函式

int main(){
	callback_function(print_text);
	//傳回調函式的地址給呼叫函式
	return 0;
}

帶引數的回撥函式形式,原理和上面差不多

void print_text(char* s){
	printf("%s",s);
}

void callback_function(void (*callbackfuct)(),char* s){
	callbackfuct(s);
}

int main(){
	callback_function(print_text,"hello world");
	return 0;
}