最新消息:

C语言 泛型指针

通常情况下,C语言只允许相同类型的指针之间进行转换。例如:一个字符型指针 sptr(一个字符串)和一个整型指针 iptr,我们不允许把 sptr 转换为 iptr 或把 iptr 转换为 sptr。但是,泛型指针能够转换为任何类型的指针,反之亦然。因此,如果有一个泛型指针 gptr,就可以把 sptr 转换为 gptr 或者把 gptr 转换为 sptr。在 C语言中,通常声明一个 void 指针来表示泛型指针。

很多情况下 void 指针都是非常有用的。例如:C语言标准函数库中的 memcpy 函数,它将一段数据从内存中的一个地方复制到另一个地方。由于 memcpy 可能用来复制任何类型的数据,因此将它的指针参数设定为 void 指针是非常合理的。void 指针同样也可以用到其他普通的函数中。例如:之前提到过的交换函数 swap2,可以把函数参数改为 void 指针,这样 swap2 就变成一个可以交换任何类型数据的通用交换函数,代码如下:

#include <string.h>
int swap2(void *x, void *y, int size) {
 void *tmp;
 if ((tmp = malloc(size)) == NULL) return -1;
 memcpy(tmp, x, size);
 memcpy(x, y, size);
 memcpy(y, tmp, size);
 free(tmp);
 return 0;
}

void 指针在用来实现数据结构时是非常有用的,因为可以通过 void 指针存储和检索任何类型的数据。我们再来看一下之前提到过的链表结构 ListElmt,回想一下,这个结构包含两个成员:data 和 next。如果 data 被声明为一个 void 指针,那么 data 就可以指向任何类型的数据。从而,我们就可以使用 ListElmt 结构来建立各种不同数据类型的链表。

定义一个链表的操作函数 list_the_next,它的功能是将一个指向的指针元素插入链表中:

int list_the_next(List *list, ListElmt *element, void *data);

要将指针 iptr 引用的整数插入名为 list 的整型链表中,element 引用的元素后面,使用以下调用。C语言允许将整型指针 iptr 赋值给参数 data,因为 data 是一个 void 指针:

retval = list_the_next(&list, element, iptr);

当然,当从一个链表中删除数据时,必须使用正确的指针类型来检索要删除的数据。这样做是为了保证当我们想对数据进行操作时数据的类型是正确的。如上所述,从一个链表中删除元素的函数 list_del_next,它的第三个参数是一个指向 void 指针的指针:

int list_del_next(List *list, ListElmt *element, void **data);

想要从 list 中 element 引用的元素后面删除一个整型变量,用如下调用方式。当函数返回时,iptr 指向已删除的数据。这是由于此操作改变了指针本身,使其指向已删除的数据,因此传递 iptr 指针的地址。

retval = list_del_next(&list, element, (void **)&iptr);

同时,此函数调用包含一个将 iptr 临时转换为一个指向 void 指针的指针的过程。正如我们将在下一节所看到的,类型转换是 C语言中一种特殊的转换机制,它允许我们临时把一种类型的变量转换为另一种类型的变量。在这里,类型转换是必要的,因为 C语言中虽然一个 void 指针与其他类型的指针相兼容,但一个指向 void 指针的指针并不一定与其他类型的指针兼容。

好了,C语言 泛型指针 就分享到这里,非常感谢你的来访。如果你喜欢本站,请不要忘记收藏本站,以便下次继续访问;也可以 关注站长微博 随时获取最新动态。你的支持就是我最大的动力!

转载请注明:爱维科斯 » C语言 泛型指针

支付宝打赏支付宝打赏 微信打赏微信打赏

如果文章对你有帮助,欢迎点击上方按钮打赏作者