网站首页 > 资源文章 正文
0. 从void说起
void*是C的产物,要说清楚void*我们先从void说起。
void即为不确定类型--类型不确定,从而所占内存不确定。因为C是强类型语言,所以void par = 10;之类的声明是万万不可的,即void类型不能声明实例对象。在C语言中,void的作用主要有以下两种:
- 对函数返回类型的限定,利用void对象的大小不确定来限制函数不能有任何返回值。-- 这就是我们常写的void作返回值的函数。
- 对函数参数类型的限定,当函数不允许接受参数时,必须用void来限定函数的参数:int func(void)。-- 当然现在没什么人会这么写了,直接写int func()即可。
1. void*是什么
不同于void,编译器允许你做类似于int par = 10; void* ppar = ∥之类的操作,因为无论指针指向什么类型,指针本身所占空间是一定的。我们可以认为void*就是一个通用指针,可以指向任意类型对象,因此void*常被称为“万能指针”。
我们都知道,指针有两个属性:所指对象的地址、长度。但是指针只存储被指向对象的地址,长度则取决于指针的类型,编译器根据指针的类型从指针指向的地址向后寻址,不同的类型则寻址范围不同,各种类型之间没有本质区别,只是解释内存中的数据方式不同。对于int*,解引用时,会从指定地址向后寻找4个字节作为变量的存储单元;对于char*,会解析1个字节。而我们将一个void类型的指针指向一个int类型的实例,实际上是抹去了这一实例的类型信息,因此在使用时我们要在心里清楚被抹去的类型信息。因此,void*也可以被称为“无类型指针”,任何类型指针都可以转为void*,它无条件接受各种类型指针。
2. 如何使用void*
既然如此,那么void*有什么用呢?其实,我们在很多接口中都能看到void*,例如
void* memcpy(void* dest, const void* src, sizt_t len);
void *memset(void *buffer, int c, int count);
任何类型的指针都可以传入memcpy和memset中,这也真正体现了内存操作函数的意义。void*帮我们屏蔽了冗余的变量类型信息,而直接将内存暴露在我们面前。
又如
ssize_t read(int fd, void* buf, size_t count);
那么,为何要如此设计?因为对于这种通用型接口,你不知道用户的数据类型是什么,但是你必须能够处理用户的各种类型数据,因而会使用void*。void*能包容的接受各种类型的指针。也就是说,如果你期望接口能接受任何类型的参数,你可以使用void*类型。但是在具体使用的时候,你必须转换为具体的指针类型。例如,你传入接口的是int*,那么你在使用的时候就应该按照int*使用。
3. void*的约束
3.1 void*可以指向任何类型的地址,但带类型的指针不能指向void*的地址
正常来说如果两个指针类型不一样的话,两个指针变量是不可以直接赋值的。如:
int* a, float* b;
a = b; //编译错误
而任何类型的指针可以赋值给void*指针,但是反过来不可以,也就是说一个有类型的指针不能指向一个void类型的变量(哪怕此时void*变量)已经指向了一个有类型的地址。
int a = 5;
int* pa = &a;
void* pb = pa;
int* pa2 = pb; //编译错误,有类型的指针变量不能指向void*变量
3.2 void*指针只有强制类型转换以后才能正常取值
既然是无类型指针,那么就不要尝试做下面的事情:
- 解引用
- 算数运算
由于不知道其解引用操作的内存大小,以及算数运算操作的大小,因此它的结果是未知的。
#include <stdio.h>
int main(void) {
int a = 10;
int *b = &a;
void *c = b;
*c; //*(int*)c就对了
return 0;
}
编译器警告如下:
warning: dereferencing 'void*' pointer
所以,void*指针只有强制类型转换以后才可以正常取值与运算。
4. void*与template
对于c++而言,对于某些泛型可以实现的功能但又想找一种轻量化的实现方法,void*也不失为一种不错的选择。
毫无疑问,在可能的情况下使用void*会提高编译速度,但这并不应该成为我们大量使用void*的理由,正如前面所看到的,void*会将很多隐藏的问题埋入深坑,相比template而言,编译期就能暴露的问题被推迟到运行时,隐含bug风险显著提升。
5. 总结
void*很强大,但是一定要在合适的时候使用;同时强转很逆天,一定要注意前后的类型是否真的能正确转换。
通俗的讲,void*:
- 这里有一片内存数据,我也不知道什么类型,给你了,你自己想怎么用怎么用吧,不过要用对奥。
- 我这里什么类型都能处理,你给我一片内存数据就可以了。
- 上一篇: 英文小百科 Null and Void
- 下一篇: The Void带来更真实完整的VR游戏体验
猜你喜欢
- 2025-01-12 恶意代码常见的编程方式
- 2025-01-12 LPL:上野不变,中下换人!LNG 2025年阵容组建完毕
- 2025-01-12 实现多态必须满足什么条件
- 2025-01-12 西门子S7-300 SCL编程笔记(附实例)
- 2025-01-12 OLED弧面显示屏VR问世 Void游戏公园团战指日可待
- 2025-01-12 C++如何定义类对象?有哪几种方式?linux C++第17讲
- 2025-01-12 C语言随机数生成
- 2025-01-12 UCGVR主题公园“The Void”宣传影像(内含Gif)
- 2025-01-12 《Void Path》10月30日登陆Steam 日恐诡异探索
- 2025-01-12 西门子S7-1200/1500PLC的程序组成之FC的应用技巧
你 发表评论:
欢迎- 05-1430个在线地图瓦片URL分享
- 05-1425个在线地图瓦片URL分享
- 05-14PixelStyle for Mac(mac照片编辑器)
- 05-14一篇文章带你了解CSS3 3D 转换知识
- 05-14我们的世界是假的?马斯克:我们生活在高文明模拟的矩阵游戏中
- 05-14【视觉AI的基石】斯坦福大学笔记!带你吃透卷积神经网络 (CNN)
- 05-14潮流 | 通过AAPE的新价目,无虑入荷未来主义服饰
- 05-14身份证查询服务API:准确识别身份证信息
- 最近发表
- 标签列表
-
- 电脑显示器花屏 (79)
- 403 forbidden (65)
- linux怎么查看系统版本 (54)
- 补码运算 (63)
- 缓存服务器 (61)
- 定时重启 (59)
- plsql developer (73)
- 对话框打开时命令无法执行 (61)
- excel数据透视表 (72)
- oracle认证 (56)
- 网页不能复制 (84)
- photoshop外挂滤镜 (58)
- 网页无法复制粘贴 (55)
- vmware workstation 7 1 3 (78)
- jdk 64位下载 (65)
- phpstudy 2013 (66)
- 卡通形象生成 (55)
- psd模板免费下载 (67)
- shift (58)
- localhost打不开 (58)
- 检测代理服务器设置 (55)
- frequency (66)
- indesign教程 (55)
- 运行命令大全 (61)
- ping exe (64)
本文暂时没有评论,来添加一个吧(●'◡'●)