C语言中void*详解及应用
void在英文中作为名词的解释为“空虚;空间;空隙”;而在C语言中,void被翻译为“无类型”,相应的void *为“无类型指针”。void似乎只有“注释”和限制程序的作用,当然,这里的“注释”不是为我们人提供注释,而是为编译器提供一种所谓的注释。
本文地址:http://www.cnblogs.com/archimedes/p/c-void-point.html,转载请注明源地址。
void的作用:
1.对函数返回的限定,这种情况我们比较常见。
2.对函数参数的限定,这种情况也是比较常见的。
一般我们常见的就是这两种情况:
当函数不需要返回值值时,必须使用void限定,这就是我们所说的第一种情况。例如:void func(int a,char *b)。
当函数不允许接受参数时,必须使用void限定,这就是我们所说的第二种情况。例如:int func(void)。
void指针的使用规则:
1.void指针可以指向任意类型的数据,就是说可以用任意类型的指针对void指针对void指针赋值。例如:
int *a;
void *p;
p=a;
如果要将void指针p赋给其他类型的指针,则需要强制类型转换,就本例而言:a=(int *)p。在内存的分配中我们可以见到void指针使用:内存分配函数malloc函数返回的指针就是void *型,用户在使用这个指针的时候,要进行强制类型转换,也就是显式说明该指针指向的内存中是存放的什么类型的数据(int *)malloc(1024)表示强制规定malloc返回的void*指针指向的内存中存放的是一个个的int型数据。
2.在ANSI C标准中,不允许对void指针进行一些算术运算如p++或p+=1等,因为既然void是无类型,那么每次算术运算我们就不知道该操作几个字节,例如char型操作sizeof(char)字节,而int则要操作sizeof(int)字节。而在GNU中则允许,因为在缺省情况下,GNU 认为void *和char *一样,既然是确定的,当然可以进行一些算术操作,在这里sizeof(*p)==sizeof(char)。
void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变量,让我们试着来定义:
void a;
这行语句编译时会出错,提示“illegal use of type 'void'”。即使void a的编译不会出错,它也没有任何实际意义。
众所周知,如果指针p1和p2的类型相同,那么我们可以直接在p1和p2间互相赋值;如果p1和p2指向不同的数据类型,则必须使用强制类型转换运算符把赋值运算符右边的指针类型转换为左边指针的类型。
float *p1;
int *p2;
p1 = p2;
//其中p1 = p2语句会编译出错,
//提示“'=' : cannot convert from 'int *' to 'float *'”,必须改为:
p1 = (float *)p2;
而void *则不同,任何类型的指针都可以直接赋值给它,无需进行强制类型转换
void *p1;
int *p2;
p1 = p2;
但这并不意味着,void *也可以无需强制类型转换地赋给其它类型的指针。因为“无类型”可以包容“有类型”,而“有类型”则不能包容“无类型”。
小心使用void指针类型:
按照ANSI(American National Standards Institute)标准,不能对void指针进行算法操作,即下列操作都是不合法的:
void * pvoid;
pvoid++; //ANSI:错误
pvoid += ; //ANSI:错误
//ANSI标准之所以这样认定,是因为它坚持:进行算法操作的指针必须是确定知道其指向数据类型大小的。
//例如:
int *pint;
pint++; //ANSI:正确
pint++的结果是使其增大sizeof(int)。
但是GNU则不这么认定,它指定void *的算法操作与char *一致。因此下列语句在GNU编译器中皆正确:
pvoid++; //GNU:正确
pvoid += ; //GNU:正确
pvoid++的执行结果是其增大了1
在实际的程序设计中,为迎合ANSI标准,并提高程序的可移植性,我们可以这样编写实现同样功能的代码:
void * pvoid;
((char *)pvoid)++; //ANSI:错误;GNU:正确
(char *)pvoid += ; //ANSI:错误;GNU:正确
GNU和ANSI还有一些区别,总体而言,GNU较ANSI更“开放”,提供了对更多语法的支持。但是我们在真实设计时,还是应该尽可能地迎合ANSI标准。 如果函数的参数可以是任意类型指针,那么应声明其参数为void *
注:void指针可以任意类型的数据,可以在程序中给我们带来一些好处,函数中形为指针类型时,我们可以将其定义为void指针,这样函数就可以接受任意类型的指针。如:
典型的如内存操作函数memcpy和memset的函数原型分别为:
void * memcpy(void *dest, const void *src, size_t len);
void * memset ( void * buffer, int c, size_t num );
这样,任何类型的指针都可以传入memcpy和memset中,这也真实地体现了内存操作函数的意义,因为它操作的对象仅仅是一片内存,而不论这片内存是什么类型(参见C语言实现泛型编程)。如果memcpy和memset的参数类型不是void *,而是char *,那才叫真的奇怪了!这样的memcpy和memset明显不是一个“纯粹的,脱离低级趣味的”函数!void的出现只是为了一种抽象的需要,如果你正确地理解了面向对象中“抽象基类”的概念,也很容易理解void数据类型。正如不能给抽象基类定义一个实例,我们也不能定义一个void(让我们类比的称void为“抽象数据类型”)变量。
C语言中void*详解及应用的更多相关文章
- 【转】void 详解
void关键字的使用规则: 1. 如果函数没有返回值,那么应声明为void类型: 2. 如果函数无参数,那么应声明其参数为void: 3. 如果函数的参数可以是任意类型指针,那么应声明其参数为void ...
- 原生JS:delete、in、typeof、instanceof、void详解
delete.in.typeof.instanceof.void详解 本文参考MDN做的详细整理,方便大家参考[MDN](https://developer.mozilla.org/zh-CN/doc ...
- void与void*详解
void关键字的使用规则: 1. 如果函数没有返回值,那么应声明为void类型: 2. 如果函数无参数,那么应声明其参数为void: 3. 如果函数的参数可以是任意类型指针,那么应声明其参数为void ...
- 【转】 void与void*详解
void关键字的使用规则: 1. 如果函数没有返回值,那么应声明为void类型: 2. 如果函数无参数,那么应声明其参数为void: 3. 如果函数的参数可以是任意类型指针,那么应声明其参数为void ...
- c语言中void *和NULL
1. int *str = NULL; #define NULL ((void *)0) 空指针实质上是有指向的指针,但它指向的地址是很小的地址,约定俗成为地址0. 2. void *vo ...
- runtime详解2
Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理.这种动态语言的优势在于:我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一 ...
- (七)C语言中的void 和void 指针类型
许多初学者对C中的void 和void 的指针类型不是很了解.因此常常在使用上出现一些错误,本文将告诉大家关于void 和void 指针类型的使用方法及技巧. 1.首先,我们来说说void 的含义: ...
- 不要伤害指针(5)--void和void指针详解
原文转载地址:http://blog.csdn.net/sunchaoenter/article/details/6587426 增加自己的想法,作为笔记. 1.概述 许多初学者对C/C++语言中的v ...
- void类型详解
void含义 void的字面意思是"无类型",void*则为"无类型指针",void*可以指向任何类型的数据. void几乎只有"注释"和限 ...
随机推荐
- 基于jquery的响应式提示框SweetAlert
介绍款交互性非常不错的jquery弹出层插件,支持消息提示.错误提示.确认框提示等.交互式体验感非常不错,比如咱们现在体验非常不错的微信支付.支付宝等完成后的效果.不过本插件至少支持IE9+.使用方式 ...
- ArcGIS Server注册地理数据库报machine:机器名[Oracle:(null)]错误的修改
环境介绍:本机安装了ArcGIS Server10.2,ArcGIS Desktop10.2,64位Oracle11g以及Oracle32位客户端.直连和服务连接都能成功. 问题:我要进行服务发布的时 ...
- 比较几种工具Python(x,y) Anaconda WinPython
浏览了一些相关的论坛,将几大工具的特点分别总结下: Python(x,y) 更新很慢,稳定性一般,默认带有很多包. WinPython 只能在windows上跑,界面友好,和Python(x,y)是 ...
- 实战:ASP.NET MVC中把Views下面的视图放到Views文件夹外
园子里写的文章的都是把控制器从传统的项目中的Controllers拿出来单独放,但很少几乎没有把视图从Views拿出去这样的文章,今天来写一个. 其实很简单!一步步解决问题就行了,下面记录如下,供需要 ...
- Oracle实例和服务知识点
shutdown是对实例而言 service是启动的,根本不代表instance就是启动的. 启动数据库基本可分为三个过程: 1,nomount(即只启动instance,而不加载数据库) 2,mo ...
- ionic 通过下载apk升级App
上篇通过更新文件升级APP,如果遇到了比如更新插件之类的问题,上篇是无法解决的,所以为了解决这个问题,需要下载apk文件升级APP. 1.配置文件如下:{'appVersion':'1.0.0', ...
- Device eth0 does not seem to be present, delaying initialization.转载
昨天在vm里面克隆了个虚拟机,克隆之后,启动了网卡起不来,已启动就报 Device eth0 does not seem to be present, delaying initialization. ...
- iOS-定时器
一.定时器的作用 在软件开发过程中,我们常常需要在某个时间后执行某个方法,或者是按照某个周期一直执行某个方法.在这个时候,我们就需要用到定时器. 二.定时器的种类 大概有三种方法:NSTimer.CA ...
- IE11之F12 Developer Tools--控制台工具(Console)
前面我们介绍了IE11的Developer Tools中的第一个工具--DOM Explorer,这篇文章介绍第二个工具--控制台(Console),使用控制台工具查看错误和其他信息.发送调试输出.检 ...
- [Solution] AOP原理解析及Castle、Autofac、Unity框架使用
本节目录: AOP介绍 AOP基本原理 AOP框架 Castle Core Castle Windsor Autofac Unity AOP介绍 面向切面编程(Aspect Oriented Prog ...