简单认识一下void

今天跟大家介绍的知识是C语言中的void关键字的用法,void在大部分小伙伴的程序中都只是用于函数无参数传入,或者无类型返回。然而我们平时所定义的变量都会有具体的类型,int,float,char等等,那是否有void类型的变量呢?答案是:不行,编译会出错。如下测试代码:
906c9e81c85e419b9c8eedd9a940447f?from=pc.jpg
上图很明显编译器不允许定义void类型的变量,变量都是需要占用一定内存的,既然void表示无类型,编译器自然也就不知道该为其分配多大的内存,于是造成编译失败。虽然void不能直接修饰变量,但是其可以用于修饰指针的指向即无类型指针void*,无类型指针那就有意义了,无类型指针不是一定要指向无类型数据,而是可以指向任意类型的数据。

void * 基本操作
大家其实在使用动态内存分配的使用就已经遇到了void *的使用,来我们一起看看如下几个标准函数的原型定义:
void* memcpy( void* _Dst, void const* _Src,size_t      _Size);
  • int  memcmp(void const* _Buf1,void const* _Buf2, size_t      _Size);
  • void* memset(void*  _Dst,int    _Val,size_t _Size );
  • void*  malloc(size_t _Size);
  • void*  realloc( void*  _Block,size_t _Size );
  • void*  calloc(size_t _Count,size_t _Size);
  • void  free( void* _Block );
  • 复制代码
    上面这些函数都是与内存操作有关的函数,而void* 类型指针使用原则是: 必须要做强制类型转换成为目标类型后才可以使用,如下测试代码:
    #include <stdio.h>
  • #include <string.h>
  • #include <malloc.h>
  • int main()
  • {
  •     int num = 0;
  •     void* pVoid = #
  •     printf("%d", *(int*)pVoid);                                //解引用前 必须强制类型转换
  •     int* p = (int*)malloc(4);                                          //赋值给目标指针 做类型转换
  •     return 0;
  • }
  • 复制代码
    使用void * 实现无类型数据封装
    void既然如此的灵活一定大有用处,如果仅仅只是用来简单地传递参数似乎有点大材小用,我们得把其用到上层的软件设计上来。在一些项目中因为数据类型的不同导致重复编写大量相同代码,为了避免这个问题C++引入了模板这个模块,C语言可以通过void* 类型的指针来完成,按下面我们以一个例子来跟大家介绍一种办法能够减少数据类型变化所带来的程序重复代码的增加。
    #include <stdio.h>
  • #include <stdlib.h>
  •   /**********************************************
  •   *                                                        代码长记不住怎么办?
  •   *                                                        点赞关注转发
  •   *                                                        这真的对我很重要
  •   **********************************************/
  • typedef struct _tag_Add
  • {
  •     int a;
  •     int b;
  •     int result;
  • }sAdd;
  • void Add(void* param)
  • {
  •     sAdd * p = (sAdd*)param;
  •     p->result = p->a + p->b;
  • }
  • typedef struct _tag_Mul
  • {
  •     float a;
  •     float b;
  •     float result;
  • }sMul;
  • void Mul(void* param)
  • {
  •     sMul * p = (sMul*)param;
  •     p->result = p->a * p->b;
  • }
  • void sCal(void* param, void* fuc)
  • {
  •     ((void(*)(void*))fuc)(param);
  • }
  • int main(void)
  • {
  •     sAdd stAdd;
  •     sMul stMul;
  •     //数据初始化
  •     stAdd.a = 10;
  •     stAdd.b = 20;
  •     stMul.a = 5;
  •     stMul.b = 5;
  •     //接口直接用
  •     sCal(&stAdd, Add);
  •     sCal(&stMul, Mul);
  •     //对应的输出
  •     printf("a + b = %d\n", stAdd.result);
  •     printf("a * b = %f\n", stMul.result);
  •     return 0;
  • }
  • 复制代码
    上面的例子可能还是无法完全彰显void*的强悍之处了,不过其主要的作用就是为了隐藏数据类型,大家也可以理解为一种数据类型的抽象处理,这也是面向对象编程的一种体现。

    最后小结
    对于void这个关键字的使用先讲这么多吧!大家一定要记得对于一些编程技巧一定要尝试着去使用,可能达到项目目标的方式有很多种,但是一些好的设计不仅仅会让你的代码增色不少,同时也会让同事们觉得你是一个喜欢专研技术的人。