C语言使用指针实现泛型

C语言中使用void指针实现更加通用的函数,void指针是一个非常特殊的存在,在ANSI标准中void指针不允许对void指针进行算术运算、解引用操作等。void指针可以指向任意类型的数据,将void指针赋值给其他类型的数据时要使用强制类型转换。
使用void指针实现通用的swap函数:

void swap(void* vp1, void * vp2, int size) {
	char* buffer = (char*)malloc(size);
	memcpy(buffer, vp1, size);
	memcpy(vp1, vp2, size);
	memcpy(vp2, buffer, size);
}

通过直接操作内存实现两个变量的交换。

使用void指针实现通用的lsearch(线性查找)函数:

//key为要查找的数,base为数组中的基地址,n为数组元素的个数,elemSize为数组元素的宽度,cmp为数组元素比较的方法(回调函数)
void* lsearch(void* key, void* base, int n, int elemSize, int (*cmp)(void* vp1, void* vp2)) {
	for (int i = 0; i < n; ++i) {
		void* num = base + elemSize * i;
		if (cmp(key, num) == 0) {
			return num;
		}
	}
	return NULL;
}

线性查找int类型数据时,调用形式为:

int array[] = {3, 5, 6, 7, 8, 12};
int size = 6;
int target = 7;
lsearch(&target, array, size, sizeof(int), intCmp);

回调函数intCmp()应该写为:

int intCmp(void* vp1, void* vp2) {
	int* num1 = vp1;
	int* num2 = vp2;
	return *num1 - *num2;
}

线性查找C语言字符串时,调用形式写为

char* array[] = {"hello", "world", "and", "nice", "to", "meet", "you"};
char target[] = "nice";
int size = 7;
lsearch(&target, array, size, sizeof(char*), strCmp);

回调函数strCmp()应该写为:

int strCmp(void* vp1, void* vp2) {
	//调用也可以修改为lsearch(target, array, size, sizeof(char*), strCmp);
	//此处str1就只用解一层引用变为:char* str1 = vp1;
	char* str1 = *(char**)vp1;
	char* str2 = *(char**)vp2;//因为这里调用时传入为指针的指针因此要解两层引用
	return strcmp(str1, str2);
}

回调函数应该为普通的全局函数或者类中的静态函数,不应该为类中非静态函数。

使用void指针实现通用的rotate函数(数据交换)
函数原型为void rotate(void* front, void* middle, void* end),函数是将front指针与middle指针之间的数值与middle指针和end指针之间的数值进行交换,如下图所示。
image
达到如下的效果如下图
image
具体实现为

void rotate(void* front, void* middle, void* end) {
	int frontSize = (char*)middle - (char*)front;
	int backSize = (char*)end - (char*)middle;
	char buffer[frontSize];
	memcpy(buffer, front, frontSize);
	memmove(front, middle, backSize);
	memcpy((char*)front + backSize, buffer, frontSize);
}

此处使用了memcpy和memmove函数,两个函数都是将一块内存中的内容复制到另一块内存中。区别是如果移动过程中有内存重叠的部分,memcpy可能会将之后使用到的内存内容进行覆盖,而memmove函数则会采用合适的方式进行内存复制以避免出现问题。因此memmove函数相比较于memcpy在执行效率上较低,因此一般除非特殊情况,否则采用memcpy。

posted @ 2021-05-08 21:18  real010  阅读(320)  评论(0编辑  收藏  举报