天天看點

函數指針的巧妙應用

對于一個函數而言,函數名是指向函數第一條指令的常量指針。而編譯器要做的就是在程式編譯之後,為每個函數配置設定一個首位址,即該函數第一條指令的位址。

一般情況下,我們可以用一個指針來儲存這個位址,而這個指針就是函數指針,該指針可以看作是它指向函數的别名,是以我們可以用該指針來調用這個函數。

下面通過一個例子,來體會函數指針的妙用。

對于C語言,由于沒有C++中的函數重載,模闆等代碼可以複用的友善操作,不太容易實作一個通用的函數來完成較多參數類型不同的類似功能。

但是,可以利用函數指針來巧妙的實作。

聲明:

#include <stdio.h>
#include <assert.h>
#include <string.h>

//定義一個函數指針類型pFun。
typedef int (*pFun)(void *ele1, void *ele2);
//比較int類型大小的函數
int int_cmp(void *ele1, void *ele2);
//比較char類型大小的函數
int char_cmp(void *ele1, void *ele2);
//查找dest指向的内容中有沒有key,n表示查找幾次,width是一次查多少個位元組
void *search(void *dest, void *key, int n, int width, int (*cmp)(void *ele1, void *ele2));
           

函數實作,注:通過傳入的不同函數指針,使得可以指向不同的回調函數,實作用一段代碼,可以執行不同類型的功能。

//查找dest指向的内容中有沒有key,n表示查找幾次,width是一次查多少個位元組
void *search(void *dest, void *key, int n, int width, int (*cmp)(void *ele1, void *ele2))
{
	int i = 0;

	assert(NULL != key);
	assert(NULL != dest);
	
	for (; i < n; ++i)
	{
		void *address = (char *)dest + i*width;
		
		if (cmp(key, address) == 0)
			return address;
	}

	return NULL;
}
           

比價int類型大小的函數

//比較int類型大小的函數
int int_cmp(void *ele1, void *ele2)
{
	assert(NULL != ele1);
	assert(NULL != ele2);

	if (*(int *)ele1 > *(int *)ele2)
		return 1;
	else if (*(int *)ele1 < *(int *)ele2)
		return -1;

	return 0;
}
           

比較char類型大小的函數

//比較char類型大小的函數
int char_cmp(void *ele1, void *ele2)
{
	assert(NULL != ele1);
	assert(NULL != ele2);

	if (*(char *)ele1 > *(char *)ele2)
		return 1;
	else if (*(char *)ele1 < *(char *)ele2)
		return -1;

	return 0;
}