一. void 类型
1. 为何不能定义 void 类型的变量
为什么不能定义 void 类型的变量?因为它是空类型,不能够为变量提供空间吗?
定义变量的本质是开辟空间,我们用 sizeof 来计算 void 类型的大小:
- 在vs2017下,不支持计算 sizeof(void)
- 在Linux中,sizeof(void)=1
可以看到不同平台下 void 类型的大小是不确定的,在 Linux 平台下 void 类型的大小是一个字节,既然为操作系统其开辟了空间,为什么又不能让它定义变量呢?
考虑 void 作为空类型,理论上是不应该开辟空间的,即使开了空间,也仅仅作为一个占位符看待。所以,既然无法开辟有效存储数据的空间,那么它定义的变量也就无法作为正常变量使用,既然无法使用,编译器干脆强制不让它定义变量。
2. void 作为函数的返回值
void作为函数返回值类型有两个作用:
- 占位符,明确告知程序员这个函数不需要返回值
- 告知编译器,这个函数的返回值无法接受
二. void* 类型
1. 能否定义 void* 类型的指针?
任何平台、任何编译器,都是可以定义 void* 类型的指针变量的。
使用 sizeof 计算 void* 的大小:
可以发现 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;
}
通常在库和系统接口的设计上,会尽量把参数和返回值设计成通用接口:
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 下都不行。