文章目录
- 一.void概要
- 二.void应用场景
- 2.1void能定义变量吗?
- 2.2void这个类型有大小吗?
- 2.3void*能定义变量吗?
- 2.4void*使用
- 2.5void*能不能进行对应的指针运算?
- 2.6void和函数返回值
- 2.7函数void类型的参数
一.void概要
void就是空的意思,一般用于函数参数,函数返回值,指针初始化的一些场景中。
二.void应用场景
2.1void能定义变量吗?
既然void也是一个类型可以像int类型这样定义吗?
int a = 10;void b = 1;//????
通过编译器来试一试:
答案是当然不行的。
2.2void这个类型有大小吗?
我们知道int是4四个字节,char是一个字节,那void是几个字节,或者是它到底有没有大小?
printf("%d", sizeof(void));
可以发现void在VS这个编译器下的大小是0,就是没有大小。
但是所有平台上的void都是没有大小的吗?接下来我在Linux平台上再做个演示:
其它的不知道不要紧,只记住在Linux平台上void大小是1就行。
通过上面例子,这也能解释了一个问题:void为什么不能定义。
首先要知道定义变量的本质是什么:在内存中开辟一块固定大小的空间。
因为void为空类型,也就是大小为0,理论上是不能开辟空间的,即使在Linux中占1个字节,那也仅仅是作为一个占位符来看待。
既然无法开辟空间,也就无法作为正常变量使用。既然无法使用,所以编译器干脆就不让他定义变量了,即使在Linux平台上也不行。
2.3void*能定义变量吗?
既然void不能定义变量,但是void*可以吗,它可以定义一个指针类型吗?
int main(){void* p = NULL;return 0;}
发现是没有任何错误的?为什么呢?void不能定义变量是因为它没有大小,不能开辟空间,而void*就不同了,它是一个指针类型,指针类型的大小是固定的:32位平台是4字节/64位平台是8字节。就是因为它有空间,所以不会报错。
2.4void*使用
void*还有什么神奇的功能呢?先看下面这个代码:
int main(){int a = 10;double b = 3.14;int* pa = &a;double* pb = &b;pa = pb;}
两个不同类型的指针能相互赋值吗?
答案是不行,虽然能成功运行,但是会有警告。
但是下面这样写可以吗?
int main(){int a = 10;int* pa = &a;void* pb = NULL;pa = pb;}
现在可以发现没有任何错误和警告,这就说明了一件事:
void*类型可以被任意一个类型接收。
现在反过来写看看可以吗?
int main(){int a = 10;int* pa = &a;void* pb = NULL;pb = pa;}
发现也是无错误,无警告。所以说:
void*类型可以接收任意类型。
上面void*的这些特性是很常见的,比如向memset,memcpy这些函数接口:
这些函数中都有用到,这样的话你再调用这些参数时,不管传进去的参数是什么类型的,它都能接收和使用。
2.5void*能不能进行对应的指针运算?
先看这段代码:
int* a = NULL;a++;a--;
这里的指针运算是什么意思呢?指针对应的±,其实就是指针向后/向前走的步长int*类型的指针++,说明指针向后移动4个字节。
通过上面的补充说明,我想大家都能猜到答案了,因为void本身是没有大小的,对它进行相应的运算是毫无意义的,因此C语言直接将这种写法当成错误了。
刚才我说的是在VS下运行的结果,肯定有人会想在Linux上void的大小是1呀,难道在那里也不能运行吗?直接看结果:
指令写到这里是没有任何报错的,说明其实在Linux下运行是没有问题的(这里的代码和在VS里一样,所以这里没有任何输出,看不到反馈)。
2.6void和函数返回值
void test(){printf("hello\n");}int main(){test();return 0;}
如果一个函数的返回类型是void,就表明这个函数是没有任何返回值的。
现在我把void去掉可以吗?
test(){printf("hello\n");}int main(){test();return 0;}
发现是可以的,但是我现在强行让函数返回一个值可以吗:
test(){printf("hello\n");return 1;}int main(){test();return 0;}
发现仍然可以。现在再来改一下,既然你有返回值,我下面接收一下会报错吗?
test(){printf("hello\n");return 1;}int main(){printf("%d\n", test());return 0;}
发现仍然能正常接收,而且我试过返回int,char这些类型都可以,返回什么就能接收到什么。但是没有写返回类型时,其默认是返回int类型。
现在我们把函数的返回值设置成void看看可不可以:
void test(){printf("hello\n");return 1;}int main(){printf("%d\n", test());return 0;}
发现这里会直接报错,所以我们知道了:
void修饰返回值时,起到一个占位符的作用,意思是明确告诉你这个函数是没有返回值的,你函数里面硬是要写也可以,但是调用时绝不能接收,只要接收就会报错。
2.7函数void类型的参数
看下面这一组代码:
void test1(){printf("hello\n");}void test2(void){printf("word\n");}int main(){test1(1, 2, 3, 4);//test2(1, 2, 3, 4);}
虽然函数里的参数都是没有的,我硬是要传过去几个参数会有什么后果呢?
先看调用第一个的结果:
发现没有任何错误,继续看调用第二个:
这里就会出现一个警告,但实际上运行还是能运行的。在我这个编译器上是一个警告,但是其它平台上可能直接就是一个错误了,接下来看看Linux平台上是警告还是错误:
发现在这里就会直接报错。通过这些例子,我们知道了:
void充当函数的形参列表,是为了告知编译器或你这个人,这个函数是不能传任何参数的。如果你函数没有任何参数里面可以加上void,这是一个挺不错的编程习惯。