【C语言】void 和 void* 类型

一. void 类型

1. 为何不能定义 void 类型的变量

为什么不能定义 void 类型的变量?因为它是空类型,不能够为变量提供空间吗?

定义变量的本质是开辟空间,我们用 sizeof 来计算 void 类型的大小:

  • 在vs2017下,不支持计算 sizeof(void)
  • 在Linux中,sizeof(void)=1

可以看到不同平台下 void 类型的大小是不确定的,在 Linux 平台下 void 类型的大小是一个字节,既然为操作系统其开辟了空间,为什么又不能让它定义变量呢?

考虑 void 作为空类型,理论上是不应该开辟空间的,即使开了空间,也仅仅作为一个占位符看待。所以,既然无法开辟有效存储数据的空间,那么它定义的变量也就无法作为正常变量使用,既然无法使用,编译器干脆强制不让它定义变量。

2. void 作为函数的返回值

void作为函数返回值类型有两个作用:

  1. 占位符,明确告知程序员这个函数不需要返回值
  2. 告知编译器,这个函数的返回值无法接受

【C语言】void 和 void* 类型_第1张图片

二. void* 类型

1. 能否定义 void* 类型的指针?

任何平台、任何编译器,都是可以定义 void* 类型的指针变量的。

使用 sizeof 计算 void* 的大小:
【C语言】void 和 void* 类型_第2张图片

可以发现 void* 的大小和其他类型指针变量的大小一样,都是4个字节。

2. 2. void* 类型指针的使用场景

  • void* 类型的地址可以被其他任何类型的指针变量接收(需要强制类型转)
  • void* 类型的指针变量也可以接收其他任意类型指针变量的值
int main()
{
	void* p = NULL;
	int* x = NULL;
	double* y = NULL;

	// 两种情况都可以编译通过
	// 不会报错误和警告
	x = (int*)p;
	y = (double*)p;

	p = x;
	p = y;
	return 0;
}

通常在库和系统接口的设计上,会尽量把参数和返回值设计成通用接口:

【C语言】void 和 void* 类型_第3张图片

3. void* 类型的指针变量能否进行位运算?

看下面一段代码:

int main()
{
	int a = 10;
	void* p = &a;
	printf("%p\n", p);
	++p;
	printf("%p\n", p);
	return 0;
}

同一段代码对比两个平台的执行结果:

  • vs2017:编译不通过,报错"void*":未知的大小
  • Linux:编译通过,结果输出:0x7fff4bf2f634 0x7fff4bf2f635,结合前面在Linux中计算 sizeof(void) = 1,所以 void* 类型的指针变量的值自增1,会是的地址的值加1。

造成如上结果的原因:两个平台支持的标准有差异

GNU计划,又称革奴计划,是由Richard stallman(理查德·斯托曼)在1983年9月27日公开发起的。它的目标是创建一套完全自由的操作系统。它在编写1inux的时候自己制作了一个标准成为GNU c标准。ANSI美国国家标准协会,它对c做的标准ANSI c标准后来被国际标准协会接收成为标准c所以ANSI C和标准c是一个概念,总体来说现在1inux也支持标准c,以后标准c可以跨平台,而GUN c一般只在linux c下应用。–来自百度
Linux 上可用的c编译器是GNU c编译器,它建立在自由软件基金会的编程许可证的基础上,因此可以自由发布。GNUC对标准C进行一系列扩展,以增强标准C的功能。–来自百度

一句话,大部分编译器是标准C,而Linux下是扩展C,Linux平台也能保证标准c的运行。

4. void* 类型的指针变量可以直接解引用吗?

结果测试不论是在 vs2017 下,还是在 Linux 下都不行。

你可能感兴趣的:(C语言,c语言)