什么是万能指针?
万能指针其实就是void *类型的指针,而void *指针一般被称为通用指针或叫泛指针。它是C语言关于纯粹地址的一种约定。当某个指针是void型指针时,所指向的对象不属于任何类型。 因为void指针不属于任何类型,不可以对其进行算术运算,比如自增,编译器不知道其自增需要增加多少。
而对于char *型指针,自增一定是指针指向的地址加1,int*型指针自增,则偏移4。这个在指针的运算中p n的解释中已经很详细的介绍过,这里不再累赘,有兴趣的可以自行查阅。
在C/C 中,在任意时刻都可以使用其它类型指针来代替void指针,或者用void指针来代替其他类型指针。 这样就可以衍生出很多比较有用的技巧。指针的本质,是其值为一个地址,那么延伸一下: 当使用关键字void声明指针变量时,它将成为通用指针变量。任何数据类型(char,int,float等)的任何变量的地址都可以赋值给void指针变量。这就是为什么把它称之为万能指针了。
万能指针使用规则- 使用前必须被初始化
- 解引用过程必须强制转换
万能指针能被任何类型指针初始化,万能指针也和其他类型指针一样,可以当做函数参数,函数返回值,以及充当函数指针皆可。
万能指针操作基本数据类型对指针变量的解引用,使用间接运算符*达到目的。但是在使用空指针的情况下,需要转换指针变量以解引用。这是因为空指针没有与之关联的数据类型。编译器无法知道void指针指向的数据类型。因此,要获取由void指针指向的数据,需要使用在void指针位置内保存的正确类型的数据进行类型转换。
万能指针充当函数返回值
万能指针充当函数返回值直接看下库中提供的动态内存申请函数即可,自己想要写的话稍微麻烦些,动态申请内存函数如下:
void *malloc(size_t size); //size_t: unsigned int
void *calloc(size_t count,size_t size); //申请具备初始化功能,malloc无此功能
而我们在实用的时候为什么要强制转换就一目了然了。
万能指针充当函数参数
当我们想要设计一个可以传入任何类型的指针的函数的时候,我们就可以把参数设计为void *类型,而对于这类函数,内存的重新申请realloc函数其实也是void *的参数,很多操作内存的函数,参数设计其实都是void *类型的指针,如果你对于C语言掌握的可以,我相信下面两个函数你应该都了解过:
void *realloc(void *pVoid,size_t size); //重新申请内存
void *memset(void *pVoid,int value ,size_t size); //设置一段内存的值
虽说万能指针充当函数指针调用函数的方式真正自己开发的时候很少用,但是有幸我的学生面试的时候就遇到过这样的一道笔试题,所以在这里就给大家讲解下,如下代码,实现通过万能指针对函数的调用:
别人会问题 (*(void(*)())pVoid)()是做什么的? 初看,大家是不是满脑子黑人问号?其实结合上面的代码看,就知道其实就是一个无返回值无参函数通过万能指针调用而已。考究的无非以下C语言知识:
- 函数指针调用函数: (*函数指针名)(参数表);
- 强制转换语法:(目标类型)变量
- 指针的类型: 去掉变量名剩下的就是指针的类型
而对函数print的函数指针是 :void (*p)() ,其实就是用(*p)替换函数名,就是该函数的函数指针,所以去掉变量名剩下的就是指针的类型,即:void (*)() ,然后pVoid 调用函数的方式: (*pVoid)(); 然后把类型拿过来强制转换即可得到:(*(void(*)())pVoid)(),明白了吧!就这么简单。
ps: 在单片机开发中,万能指针往往用来实现数据的非易失存储。所谓非易失存储,就是数据改写后在掉电后仍然能保持。有兴趣的可以自我拓展下哦
尾言文章都是手打原创,每天最浅显的介绍C语言、C ,windows知识,喜欢我的文章就关注一波吧,每天带你学习C/C 不同的知识,也可以看到最新更新和之前发表的文章哦。如果足下基础比较差,不妨关注下人人都可以学习的视频教程
《C语言51课视频教程合集》
《C 45课视频教程》
通俗易懂,深入浅出,一个视频只讲一个知识点。视频不深奥,不需要钻c研,在公交、在地铁、在厕所都可以观看,随时随地涨姿势
如果今天学到知识的,可以在留言区留言学到了哦,你的响应是我坚持的最大动力,如果喜欢可以,也可以点赞,转发,收藏,三连哦,这真的对我很重要!!这真的对我很重要!!
,