文章目录

    • 一.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,这是一个挺不错的编程习惯。