C語言進階:指針的進階(5)

函數指針數組

//整型數組 - 存放整型變量
int arr[10];
//字符數組 - 存放字符變量
char ch[5];
//指針數組 - 存放指針變量
int* arr[10];
//函數指針數組 - 存放函數指針
int(*pfar[10])(int, int);

指針數組存放指針變量,函數指針數組存放函數指針,故元素類型為函數指針類型。

函數指針數組的定義

int Add(int x, int y) {//int(*)(int,int)
	return x + y;
}
int Sub(int x, int y) {//int(*)(int,int)
	return x - y;
}
int Mul(int x, int y) {//int(*)(int,int)
	return x * y;
}
int Div(int x, int y) {//int(*)(int,int)
	return x / y;
}
int main() {
	//函數指針數組 - pfArr
	int(*pfArr[4])(int, int) = { Add,Sub,Mul,Div };
	return 0;
}

類型相同的函數,存放在同一個函數指針數組中。一般功能相似的函數,其類型也相同。

函數指針數組的使用

利用函數指針數組實現計算器,以簡化調用過程。

轉移表

//計算器實現1.0
void menu() {
	printf("**********************************\n");
	printf("*****  1.Add  ******  2.Sub  *****\n");
	printf("*****  3.Mul  ******  4.Div  *****\n");
	printf("************  0.exit  ************\n");
	printf("**********************************\n");
}
int main() {
	int (*pfArr[10]) (int, int) = { 0,Add,Sub,Mul,Div };//數組下標和選項序號匹配
	int input = 0;
	int a = 0;
	int b = 0;
	do {
		menu();
		printf("請選擇:>");
		scanf("%d", &input);
		if (0 <= input && input <= 4) {
			if (input == 0) {
				printf("退出遊戲\n");
				break;
			}
			else {
				printf("請輸入操作數\n");
				scanf("%d %d", &a, &b);
				printf("ret == %d\n", pfArr[input](a, b));
				break;
			}
		}
		else {
			printf("輸入錯誤\n");
			break;
		}
	} while (input);
	return 0;
}

函數指針數組實現不同選擇情況下,通過函數地址“跳轉”到不同的函數的功能。

這樣的函數指針數組成為轉移表。(跳轉功能)

回調函數

若不想舍棄switch語句,還可以這樣簡化代碼3.0,代價為創建全局變量。若不想創建全局變量,可以使用2.0

/******
* 計算器實現
* 2.0
******/
void Calc(int (*pf)(int,int)) {
	int a = 0;
	int b = 0;
	printf("請輸入操作數:>");
	scanf("%d %d", &a, &b);
	printf("%d\n", pf(a, b));
}
int main() {
	int input = 0;
	do {		menu();
		printf("請選擇:>");
		scanf("%d", &input);
		switch (input) {
		case 0:
			printf("退出成功\n");
			break;
		case 1:
			Calc(Add);
			break;
		case 2:
			Calc(Sub);
			break;
		case 3:
			Calc(Mul);
			break;
		case 4:
			Calc(Div);
			break;
		default:
			printf("請重新選擇\n");
			break;
		}
	} while (input);
	return 0;
}
/******
* 計算器實現
* 3.0
******/
int (*pfArr[10])(int, int) = { 0,Add,Sub,Mul,Div };
int input = 0;
void Call() {
	int a = 0;
  int b = 0;
	printf("請輸入操作數:>");
	scanf("%d %d", &a, &b);
	printf("%d\n", pfArr[input](a, b));
}
int main() {
	do {
		menu();
		printf("請選擇:>");
		scanf("%d", &input);
		switch (input) {
		case 0:
			printf("退出成功\n");
			break;
		case 1:
		case 2:
		case 3:
		case 4:
			Call();
			break;
		default:
			printf("請重新選擇\n");
			break;
		}
	} while (input);
	return 0;
}

如下圖所示,被通過函數指針調用的函數叫做回調函數,回調函數即使第三方調用調用函數的參數也在其中被調用。

若想在調用函數中隨條件變化而調用不同的函數,就必須使用回調函數的方法:調用函數中使用函數指針,指向不同函數。回調函數在大型工程中顯得非常方便。

在這裡插入圖片描述

指向函數指針數組的指針

int arr[10];
int(*parr)[10] = &arr;//整型數組指針
char(*pch)[10] = &ch;//字符數組指針
//指向整型數組指針的指針
int(*(*pparr))[10] = &parr;
//指向字符數組指針的指針
char(*(*ppch))[10] = &pch;

//函數1.
int Add(int x, int y) {
	return x + y;
}
//函數指針2.
int (*pf)(int, int) = Add;
//函數指針數組3.
int (*pfArr[10])(int, int) = { Add };
//指向函數指針數組的指針4.
int(*(*ppfArr)[10])(int, int) = &pfArr;

前面已經交代,指針去掉*號和指針名,就是指向的變量類型;去掉指針名就是指針的類型。

反過來,定義數組指針,需要得到指針所指向的數組的類型。1.先寫出指針名,在其前面加*;2.寫出數組的類型int()[10]

定義指向函數指針數組的指針,依次寫出如下內容:

1.函數 —— 得到函數類型:int(int, int)

2.函數指針 —— 得到函數指針類型:int(*)(int, int)

3.函數指針數組 —— 得到函數指針數組的類型:int(*[10])(int, int)

4.指向函數指針數組的指針

在這裡插入圖片描述

從後往前看,指向函數指針數組的指針去掉*和指針名就是函數指針數組的類型,函數指針數組去掉*和指針名就是函數指針類型,函數指針去掉*和指針名就是函數類型。

在研究下去就沒有必要瞭,指針放在數組裡,數組被指針所指向……

總結

本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!

推薦閱讀: