您的位置 首页 传感器

深化了解void类型

1空指针一般来说,程序的起始地址是从代码区的0地址开始存放的(注:如果插入一个内存分布图,则更能说明问题,此处省略),但实际上现代操

1.空指针

一般来说,程序的开端地址是从“代码区”的0地址开端寄存的(注:假如刺进一个内存分布图,则更能阐明问题,此处省掉),但实际上现代操作体系并非如此,却保存了从0开端的一块内存。至于这块内存到底有有多大,与详细的操作体系有关。假如程序企图拜访这块内存,则体系提示反常。

为什么操作体系不是保存一个字节呢?因为内存办理是按页来进行的,因而无法做到独自保存一个字节。尽管如此,但仍是有极少量体系设定RAM区从0地址开端,但指向有用变量的指针不会指向0地址。即便“代码区”从0地址开端,但在任何情况下,0地址都不是C言语中任何函数的开端地址,因而指向有用函数地址的指针也不会指向0地址。

☛课外常识延伸

尽管80C51微控制器XDATA区(外部RAM)是从0地址开端的,但只需对保存在0地址中的变量不进行取地址操作(&操作),即可有用地确保指针不会指向0地址。

与此一起,尽管32位ARM7微控制器也是从0地址开端的,但这块内存仅用于寄存中断向量代码,而不是程序中的有用变量地址,因而即运用空指针来判别指针的有用性,其仍然是可行的。

根据此,所以将空指针界说为指向0地址的指针。毫无疑问,任何一种指针类型都有一个特别的指针值,即空指针。它既不会指向任何目标或函数,也不是任何目标或函数的地址。而未初始化的指针,则彻底或许指向任何当地。

由此可见,空指针与未初始化的指针是彻底不同的两个概念。那么,将如安在程序中取得一个空指针呢?

2.空指针常量与NULL

规范C规则,在初始化、赋值或比较时,假如一边是变量或指针类型的表达式,则编译器能够确认另一边的常数0为空指针,并生成正确的空指针值。即在指针上下文中“值为0的整型常量表达式”在编译时转化为空指针。

为了让程序中的空指针运用愈加清晰,规范C专门界说了一个规范预处理宏NULL,其值为“空指针常量”,一般为0或(void *)0,即在指针上下文中NULL与0是等价的,而未加润饰的0也是彻底能够承受的。因为void *指针的特别赋值特点,比方:

#define NULL ((void *)0)

当NULL界说为((void *)0)时,即NULL是能够赋值给任何类型指针的值,它的类型为void*,而不是整数0,因而初始化“FILE *fp = NULL;”是彻底合法的。

而为了区别整数0和空指针0,当需求其它类型的0的时分,即便或许作业,但也不能运用NULL,假如这样处理其格局是过错的,这在非指针上下文中是不能作业的。特别地,不能在需求ASCII空字符(NUL)的当地运用NULL。假如的确需求,则能够自界说为:

#define NUL

由此可见,常数0是一个空指针常量,而NULL仅仅是它的一个别号。

3.空指针的用处

一般来说,未初始化是不能运用的不合法指针,因为它彻底有或许指向任何当地,然后导致程序无法判别它为不合法指针。因而,不论指针变量是大局的仍是部分的、静态的仍对错静态的,都应该在声明它的一起进行初始化,要么赋予一个有用的地址,要么赋予NULL。

规范C规则,大局指针变量的默认值为NULL,而关于部分指针变量则有必要清晰地指定其初值。因而,void一般用于指针变量的初始化,用来判别一个指针的有用性。比方:

unsigned char *pucBuf=(void *)0;//界说pucBuf为unsigned char类型指针并初始化为空指针

假如后续的代码忘掉初始化指针而直接运用的话,则或许形成程序失利。尽管空指针也是不合法指针,但能够经过程序判别并告知程序员代码或许有问题。也就是说,假如一开端就将指针初始化为空指针,则可防止程序反常。比方:

if(pucBuf==0){

return error;//假如pucBuf为空指针,则回来参数过错

}

因为void类型指针的不确认性,因而它能够指向恣意类型的数据,那么只需在运用时做一个简略的强制类型转化就能够了。比方:

unsignned char*pcData = NULL;//界说pcData为unsigned char类型指针

void*pvData;//界说pvData为void类型指针

pvData = pcData;//无需进行强制类型转化

pcData = (unsigned char*) pvData;//将pvData强制转化为unsigned char类型指针

明显不存在void类型的目标,也就是说,当目标为空类型时,其巨细为0字节;当目标未确认类型时,那么它的巨细也是未确认的,因而不能声明void类型变量。比方:

void a;//不合法声明

已然上述声明是不合法的,那么,也就不能将sizeof运算符用于void类型。也就意味着,编译器不知道所指目标的巨细,因为指针的算术运算总是根据所指目标的巨细的,因而不允许对void指针进行算术运算。

总归,在指针声明中,void *表明通用指针的类型。假如void作为函数的回来类型,则表明不回来任何值。假如void坐落参数列表中,则表明没有参数。

4. 用无类型指针作为函数参数

因为C言语中最小长度的变量为char类型(包含unsigned char、signed char等),其sizeof(char)的成果为1,而其它任何变量的长度都是它的整数倍。比方,假如运用SDCC51编译器,其sizeof(int)为2。因为通用swap函数函数不知道需求交流的变量的类型,所以需求一个参数给出相应的指示。因为C言语的变量类型多种多样,因而不或许为每一种变量类型编号,并且swap并不关怀变量的真实类型,所以能够用变量的长度替代变量类型。通用swap函数的原型为:

void swap(void *pvData1, void *pvData2, int iDataSize)

将a,b两个变量(变量类型有必要相同)的值交流的代码如下:

swap(&a, &b, sizeof(a));

通用swap排序函数的参阅代码见程序清单1.1。

程序清单1.1通用swap排序函数

1void swap (void *pvData1, void *pvData2, int iDataSize)

2{

3unsigned char *pcData1 = NULL;

4unsigned char *pcData2 = NULL;

5unsigned charucTmp1;

6

7pcData1 = (unsigned char *)pvData1;

8pcData2 = (unsigned char *)pvData2;

9

10do {

11ucTmp1 = *pcData1;

12*pcData1= *pcData2;

13*pcData2= ucTmp1;

14pcData1++;

15pcData2++;

16} while (–iDataSize > 0);

17}

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/yingyong/chuanganqi/257558.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部