10.4 void和void*的区别
虽然在代码中经常见到的void和void*,但是可能不少初学者对它们并不是很了解,接下来看看它们适用于哪些情况。首先来看void,void使用最多的场景是设置函数的返回值类型,如:
include<stdio.h>
void print()
{
printf("Hello World\n");
return;
}
int main()
{
print();
return 0;
}
运行结果:
Hello World
分析上面的代码,print函数的返回值类型为void,意味着其没有返回值,需要注意的是,如果没有对函数的返回值声明任何的类型,那么默认返回值为int型,并不是void类型。看看下面的代码。
include<stdio.h>
include<stdlib.h>
sum(int a[],int n)
{
int i,sm;sm=0;
for(i=0;i<n;i++)
sm+=a[i];
return sm;
}
int main(void)
{
int a[4]={1,2,3,4};
printf("%d\n",sum(a,4));
return 0;
}
运行结果:
10
void也可以作为函数的参数,如果参数没有返回值,那么可以用void来表示,如:
include<stdio.h>
int main(void)
{
printf("Hello World\n");
return 0;
}
运行结果:
Hello World
分析上面的运行结果,因为main函数没有携带任何参数,所以将其参数设置为void,表示其没有传递任何参数信息。
切记不要用void来定义参数,如:
void n;
以上定义在编译时会出现“error C2182:'n':illegal use of type'void'”错误,由此可以看出,void的用途也就体现在两个方面:一是限定函数的返回值,二是限定函数的参数。
接下来介绍void的使用。void同样可以用来限定函数的返回值和参数,而且可以用来定义变量,但是切记不可将其理解为指向void类型的指针。看看下面的代码。
include<stdio.h>
int main()
{
void*n;
printf("void*类型的指针定义成功\n");
return 0;
}
运行结果:
void*类型的指针定义成功
分析上面的运行结果,我们成功地定义了void*类型的指针,该指针并不是某些初学者所理解的空指针,而是一种特殊类型的指针,与之前定义的确定类型指针的不同之处在于,该指针是一种可以指向任意类型的指针,因此称作万能指针。看看下面的代码。
include<stdio.h>
int main()
{
void*n;
int a=0;
int*p;
char c='A';
p=&a;
printf("p=%d,p=%d\n",p,p);
n=p;
printf("n=%d,n=%d\n",n,(int*)n);
char*pc;
pc=&c;
printf("pc=%d,pc=%d\n",pc,pc);
n=pc;
printf("n=%d,n=%d\n",n,(char*)n);
return 0;
}
运行结果:
p=1245048,*p=0
n=1245048,*n=0
pc=1245040,*pc=65
n=1245040,*n=65
分析上面的代码,我们定义了可指向任何类型的指针n,首先将该指针指向int型变量,然后将该指针指向char类型的变量,由此可以看出,void定义的指针类型的确是一种可指向任何类型的指针,没有固定的指向。正是因为void类型的指针没有固定类型,所以不可以对void类型的指针进行自加或者自减运算,如:
include<stdio.h>
int main()
{
void*n;
int a=9;
int*pa;
pa=&a;
printf("pa=%d\tpa=%d",pa,pa);
pa++;
printf("pa++=%d",pa);
//printf("%d",n++);
return 0;
}
运行结果:
pa=1245048*pa=9
pa++=1245052
分析上面的代码,我们对整型指针pa做了自加运算,同时在代码中还有一句打印语句,用于实现对void类型的指针进行自加运算。但是打印语句被注释掉了,如果没有注释掉,那么编译的时候就会出现如下错误:
error C2036:'void*':unknown size
所以在使用void类型的指针时需要注意,由于其所指向的类型是不确定的,因此不可对其进行自加或者自减运算。