C语言 — void的用法解析[通俗易懂]

C语言 — void的用法解析[通俗易懂]C语言-void的用法解析简介​ void中文翻译为”无类型”,有的也叫”空类型”。常用在程序中对定义函数的参数类型、返回值、函数中指针类型进行声明。用法​ void应用最广泛的就是跟指针结合,即void* //无类型指针,也称为空指针,可以指向任何类型的数据 //注意一点:当我们需要使用void类型的的指针变量区指向 某一类型的变量的时候,必须要对其进行类型转换​ 这里补充一点:因为我们在定义一个指针变量的时候第一件事就是指定我们指针变量所指向的变量的类型。一

大家好,又见面了,我是你们的朋友全栈君。

一、简介

​ void 中文翻译为”无类型”,有的也叫”空类型”。常用在程序中对定义函数的参数类型、返回值、函数中指针类型进行声明。

二、用法

首先应该注意一点的是void类型是不同于其他常见类型的,即void 类型不能够用来申明变量和常量。因为我们申明变量的时候需要明确告诉编译器,该变量是什么类型,比如说是int 或 char类型,这样编译才好为这个变量去分配存储空间,但你不能告诉编译器说我这是一个”空类型”,这样的话编译器肯定不会干的,自然你编译的时候会报错: "illegal use of type 'void'"

总的来说,void应用最广泛的就是跟指针结合,而void和指针的结合也大大扩展了指针的可能性。

void *	
/*无类型指针,也称为空指针,可以指向任何类型的数据 *注意一点:当我们需要使用void 类型的的指针变量去指向某一类型的变量的时候,必须要对其进行类型转换 */

我们在定义一个指针变量的时候第一件事就是指定我们指针变量所指向的变量的类型。一旦被指定,我们的指针变量就只能指向这一类型的变量,即只能保存这一类变量的地址。之所以这样呢,是跟我们计算机的存储数据的形式有关。简单来讲,就是不同类型的变量被分配的内存大小是不一样的,当对指针变量去进行解引用的时候,就必须保证可以取出来正确的内存内容。

第一点,我们先看一个例子,这里有一个典型的应用案例就是malloc函数,我们经常会使用到的内存申请函数。请看一个小例子:

int *p_int;
p_int = (int *)malloc(sizeof(int));

先要说明一点的是,malloc()分配了内存,但没有为它指定名字,但是它却可以返回那块内存第一个字节的地址。因此,可以把那个地址赋值给一个指针变量,并使用该指针来访问那块内存。因为char代表一个字节,所以传统用法上曾将malloc()返回值定义为指向char的指针类型。然而,ANSIC标准使用了一个新类型:指向void的指针。这一类型被用作“通用指针”。

因为malloc分配内存返回的是一个void 类型的指针,所以我们在使用的时候通常会对该指针类型进行强制转换为我们所需要的的指针类型。这样我们就可以使用malloc()来为我们分配任意大小的内存空间(当然了,因为malloc是在堆区分配的内存,所以我们申请的这块内存的大小应该小于堆区的大小)。

我们知道两个指针变量p1,p2,只有当它们类型相同的时候才能进行互相赋值。如果p1,p2指向不同的数据类型,那么他们必须进行类型转换才能相互赋值。比如:

float *p1;
int *p2;
p1 = p2;

执行上面一段程序的时候我们会发现会报错,提示”cannot convert from 'int*' to 'float *`”,若改为

int *p1;
void *p2;
p1 = p2;

此时就不会报错,因为赋值运算符的右边进行了隐式类型转换。当然了,我们也可以进行强制类型转换,即使用括号进行类型转换,比如:

int *p1;
void *p2;
p1 = (int *)p2;

从上面的例子可以看出,当我使用void去修饰指针的时候,这种通用类型的指针可以很方便的和其他类型的指针之间进行相关转换。

void另一个重要的应用则就是跟函数进行结合主要有以下两个方面的应用。

  1. 对函数返回的限定;
  2. 对函数参数的限定;

三、总结

  1. 如果函数没有返回值那么应声明为void 类型

    C语言中有一个规则,凡是不加返回值限定的函数,就会被编译器作为整型值(int)处理。但是许多人却误以为其为void类型。

    因为C语言不像C++那样有很严格的类型安全检查。所以为了避免混,对于任何函数必须制定其返回值类型。如果函数没有返回值一定要声明为void类型。这样既可避免混淆也方便自己和别人查看我们的代码。

  2. 如果函数无参数,那么应该声明其参数为void

    如果我们所写的函数不接受任何参数,那么一定要指明其参数为void。

  3. 如果函数的参数可以是任意类型指针,那么应声明其参数为void *

    这里有几个比较常用到的函数,都采用了此规则。同样,这一规则在我们日常编程中应用也很广泛。

    /* 内存操作函数 */
    void *memcpy(void *dest, const void *src, size_t len);
    void memset(void *buffer, int c , size_t num);
    int memcmp(const void *sl, const void *s2, size_t n);
    
    /* 内存分配与释放函数 */
    void *malloc(size_t size);
    void *calloc(size_t num, size_t size);
    void *realloc(void *ptr, size_t size);
    void free(void*ptr);
    

    可以看到我们用void 来修饰了函数参数类型,即我们可以传任意类型指针。这也体现内存操作函数的意义,因为它操作的对象仅仅是一片内存,而不论这片内存存储的数据是什么类型。

  4. 使用void类型指针时应该注意

    按照C标准规定,我们不能对void型指针进行运算。对有类型的指针进行算法操作的时候我们知道,因为其有具体所指向的类型,所以对其的运算是以其所指向的数据类型为单位进行的。而void的含义为空或者说无类型,所以就无法对其进行算术运算。
    在这里插入图片描述
    运行结果为:
    在这里插入图片描述

    我们如果要对void类型指针进行算术运算的话就必须进行类型转换,这里有一个典型的应用案例就是malloc函数,我们经常会使用到的内存申请函数。请看一个小例子:
    在这里插入图片描述
    先要说明一点的是,malloc()分配了内存,但没有为它指定名字,但是它却可以返回那块内存第一个字节的地址。因此,可以把那个地址赋值给一个指针变量,并使用该指针来访问该块内存。

    因为malloc分配内存返回的是一个void 类型的指针,所以我们在使用的时候通常会对该指针类型进行强制转换为我们所需要的的指针类型。

  5. void 不能代表一个真实的数据类型

    这个前面提到过,因为void在C语言中解释为,或者无类型,所以它当然无法代表一个真实的数据类型了。不过我们可以对其进行类型转换,这样它又可以变成各种各样的数据类型,所以我们可以将其理解成一个”抽象数据类型“。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/144660.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 15种手机游戏引擎和开发工具介绍

    15种手机游戏引擎和开发工具介绍工欲善其事,必先利其器。对移动游戏开发者来说,高效实用的开发工具必不可少。近日,英国著名产业杂志《Develop》刊出了一篇文章,作者艾伦·李在文中推荐了15种移动游戏开发工具,从游戏引擎,到音效制作、推广等工具都有涉及。以下为原文主要内容编译。引擎和移动开发工具包Marmalade简介:Marmalade被很多人认为是跨平台制作C++游戏的最佳平台。通过MarmaladeSDK,开发者可以在单一的Marmalade项目文件夹中打开Xcode或VisualStudio,将

    2022年5月22日
    134
  • 键值对操作

    键值对RDD通常用来进行聚合计算。我们一般要先通过一些初始ETL(抽取、转化、装载)操作来将数据转化为键值对形式。键值对RDD提供了一些新的操作接口(比如统计每个产品的评论,将数据中键相同的分为一组,将两个不同的RDD进行分组合并等)。1.动机Spark为包含键值对类型的RDD提供了一些专有的操作。这些RDD被称为pairRDD。PairRDD是很多程序的构成要素,

    2022年4月8日
    86
  • Java:StringBuilder的基本使用

    Java:StringBuilder的基本使用概述StringBuilder表面看起来是用来拼接、处理字符串的一个工具类,但它的内部实现其实是处理字符序列。StringBuilder比String具有使用更加方便、运行效率更高的特点。StringBuffer是在StringBuilder的基础上多了线程安全(同步访问)。拼接、反序、替换、删减、插入append(),用于拼接,可接受字符串以及所有的基本数据类型的数据。StringBuildersb=newStringBuilder();sb.ap

    2022年7月17日
    14
  • phpStudy2016 配置多个域名期间遇到的问题

    phpStudy2016 配置多个域名期间遇到的问题

    2021年10月10日
    43
  • BestSync同步软件 同步 VM 虚拟机里的Linux系统下Tomcat webapps里的项目

    BestSync同步软件 同步 VM 虚拟机里的Linux系统下Tomcat webapps里的项目

    2021年8月31日
    88
  • 多少行代码可以申请软件著作权_python申请软件著作权

    多少行代码可以申请软件著作权_python申请软件著作权在申请软件专利或著作权时,如何快速统计源码行数。其实我们可以利用vs2010的文件搜索功能结合正则表达式,来遍历所有文件得出总行数.

    2022年9月22日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号