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;}