void* 作为函数参数,函数返回值的用法

c语言中*表示变量为指针类型如int* p, double* q。虽然他们指向数据类型不同但是他们在内存中所占的大小是一致的,根据机器的字节码确定。sizeof(p) == sizeof(q)。但是对于他们的加减法运算有差异。p+1指针移动4个内存地址。q+1移动8个内存地址。

viod* p是一个指向类型不明确的指针,也就是说p+1不明确移动多少个内存地址。但是我们可以灵活地将其进行类型转换使其转换为需要的数据类型。这样的好处是可以实现灵活的泛型编程。比如排序算法我们不知道需要排序的数据类型,在c++中可以使用模板进行实现。但是在c语言中需要使用函数指针或者void*实现。定义排序接口:
void InsertSort(void* arr, int n, int elem_size, int(*cmp)(void*, void*));
这里由于数组的数据类型未定所以传入void*,同时传入数据量n,数据类型大小elem_size。对于不同数据类型的比较函数指针。

函数指针

函数指针指指向函数的指针,定义方式为ret (*p)(arg,...)p是一个指向形参列表为arg,...,返回值为ret类型的函数指针。函数指针可以当做形参进行传递。int (*p)(int ,int)p是一个指向返回值为int,形参为(int,int)的函数指针。定义方式如下:


typedef int(*Fp)(int,int);//定义函数指针类型名字
bool max(int a, int b){
	return a>b?true:false;
}
int main(){
	bool (*p)(int,int);
	p = max;
	p(1,2);//调用
	p(2,3);
	(*p)(1,3);
	
	//另一种定义方式
	Fp q;
	q = max;
}

进一步来看void的排序函数。首先对于不同数据类型定义比较函数:

int compare_int(void *elem1, void *elem2)
{
	return (*(int *)elem1 - *(int *)elem2);
}
int compare_double(void *elem1, void *elem2)
{
	return (*(double *)elem1 > *(double *)elem2) ? 1 : 0;
}

排序函数:

void InsertSort(void* arr, int n, int elem_size, int(*cmp)(void*, void*)) {
	int i, j;
	char* elem_addr1, *elem_addr2;
	char* key_addr;
	char* tmp = (char*)malloc(elem_size);
	for (i = 1; i < n; i++) {
		key_addr = (char*)arr + i * elem_size;
		memcpy(tmp, key_addr, elem_size);
		j = i - 1;
		elem_addr1 = (char*)arr + j * elem_size;
		while (j >= 0 && cmp(elem_addr1, tmp) > 0){	
			elem_addr1 = (char*)arr + j * elem_size;
			elem_addr2 = (char*)arr + (j + 1) * elem_size;
			memcpy(elem_addr2, elem_addr1, elem_size);
			j--;
		}
		elem_addr2 = (char*)arr + (j + 1) * elem_size;
		memcpy(elem_addr2, tmp,elem_size);
	}
	free(tmp);
}

测试函数:

int main(){
	int num_int[8] = { 8,7,6,5,4,3,2,1 };
	InsertSort(num_int, 8, sizeof(int), compare_int);
	return 0;
}
	

你可能感兴趣的:(C/C++,c++)