int型整数交换
void swap(int *ap, int *bp)
{
int temp = *ap;
*ap = *bp;
*bp = temp;
}
因为参数声明的是int*类型,所以只会操作4字节的内存空间,这只适用于int类型,不具备通用性。
通用类型交换
void swap(void *vp1, void *vp2, int size)
{
char buffer[size];
memcpy(buffer, vp1, size);
memcpy(vp1, vp2, size);
memcpy(vp2, buffer, size);
}
这里我们使用void*类型(任何类型指针都可以转为void*),但是void*会造成信息损失,编译器无法确定以vp1为首地址的变量该取多少个字节。因此,不能使用取值操作*vp1,而直接使用memcpy进行字节层面的拷贝。
int x = 17, q = 37;
swap(&x, &q, sizeof(int));
double d = 3.14, e = 2.78;
swap(&d, &e, sizeof(double));
运行结果x:37, q:17, d:2.78, e: 3.14
但是,如果两个变量是不同的类型则会产生一定的问题,如下:
int i = 44;
short s = 5;
swap(&i, &s, sizeof(short));
即0x2c 00 00 00与0x05 00 00 00按2字节进行交换
输出 i: 5, s: 44
如果想传递不同类型的变量,则需要要为函数提供更多的类型信息。
字符串交换
char *hushand = strdup("Fred");
char *wife = strdup("Wilma");
swap(&hushand, &wife, sizeof(char*));
这里交换的是char*指针,并不是内存中存储的数据。
char *husband = strdup("Fred");
char *wife = strdup("Wilma");
swap(husband, wife, sizeof(char*));
这里传入的是char*指针,同时sizeof(char*)为4字节,编译器会执行4字节交换
输出结果就是husband: Wilm, wife: Freda
查找
int lsearch(int key, int array[], int size) {
for(int i = 0; i < size; i++) {
if(array[i] == key) {
return i;
};
}
return -1;
}
因为array实际上是数组首地址,在传递的过程中我们损失了数组长度的信息,因此在函数参数中我们需要进行补充。
通用版本
void* lsearch(void *key, void *base, int n, int elemSize) {
for(int i = 0; i < n; i++) {
void *elemAddr = (char*)base + i * elemSize;
if(memcmp(key, elemAddr, elemSize) == 0)
return elemAddr;
}
return NULL;
}
在通用版本中,我们通过void*来进行传递,但是这种方式会进一步损失元素字节大小的信息,因此在函数参数中我们需要进行补充。
一般情况下,我们采用如下方式进行处理
void *elemAddr = base + i * elemSize;
但是void*中不包含元素字节大小的信息,因此一般编译器中不允许如上操作,最常见的方式就是将void*类型强制转为char*类型来进行操作。
下节课,我们会将比较函数也进行传递,来实现在标准库中我们所见到的一般形式,如下所示:
void *lsearch(void *key, void *base, int n, int elemSize, int (*cmpfn)(void*, void*));