void和void指针解析(原)
(一)基本概念
void 类型:空类型,用于特殊目的的没有操作,也没有值的类型。不能被显式或隐式的转换为任意非空类型,可以通过强制类型转换为void类型。
void指针:指向任何对象的指针都可以转换为void*类型指针,且不会丢失信息。在ANSI C使用类型void*代替char*作为通用指针的类型。
(二)使用方法
1. void的使用
第一种是:对函数返回的限定
在不加返回值类型限定的情况之下,编译器会将其处理为整型的类型。例如以下的情况:
#include <stdio.h>
// 参考了别人写void的例子,但是这个例子十分形象
// 的表明了不加返回类型值限定时,编译器的处理规则。
add (int a, int b)
{
return a + b;
}
int main(int argc, char* argv[])
{
printf("2 + 3 = %d", add (2, 3));
return 0;
}
对于每个函数,我们都要明确的指定其返回值的类型。该void的时候,就void。不要省略不写,这回带来大麻烦。
第二种:对函数参数的限定
当函数不允许接受参数时,必须使用void限定。例如以下两种情况:
在C语言下:
#include <stdio.h>
// 以下两个函数都可以进行正常的编译,不会报错。
// C的容忍度还是很大的。。。
int func()
{
return 1;
}
int func1(void)
{
return 1;
}
int main(int argc, char* argv[])
{
printf("%d\n", func(2));
printf("%d\n", func1(2));
return 0;
}
运行结果:
在C++语言下:
#include <iostream>
int func()
{
return 1;
}
int func1(void)
{
return 1;
}
int main(int argc, char* argv[])
{
std::cout << func(1) << std::endl;
std::cout << func1(1) << std::endl;
return 0;
}
运行结果:
在C语言中,可以给无参数的函数传送任意类型的参数,但是在C++编译器中编译同样的代码则会出错。在C++中,不能向无参数的函数传送任何参数。
2. void指针的使用
在《C++ primer》中,对void指针的作用做了阐述:与另一指针比较;向函数传递void指针或从函数返回void指针;给void指针赋值。
由于void指针可以指向任意类型的数据,亦即可用任意数据类型的指针对void指针赋值,因此还可以用void指针来作为函数形参,这样函数就可以接受任意数据类型的指针作为参数。
以下摘至sgi stl中的代码片段:
/* __n must be > 0 */
static void* allocate(size_t __n)
{
void* __ret = 0;
if (__n > (size_t) _MAX_BYTES) {
__ret = malloc_alloc::allocate(__n);
}
else {
_Obj* __STL_VOLATILE* __my_free_list
= _S_free_list + _S_freelist_index(__n);
// Acquire the lock here with a constructor call.
// This ensures that it is released in exit or during stack
// unwinding.
ifndef _NOTHREADS
/*REFERENCED*/
_Lock __lock_instance;
endif
_Obj* __RESTRICT __result = *__my_free_list;
if (__result == 0)
__ret = _S_refill(_S_round_up(__n));
else {
*__my_free_list = __result -> _M_free_list_link;
__ret = __result;
}
}
return __ret;
}
/* __p may not be 0 */
static void deallocate(void* __p, size_t __n)
{
if (__n > (size_t) _MAX_BYTES)
malloc_alloc::deallocate(__p, __n);
else {
_Obj* __STL_VOLATILE* __my_free_list
= _S_free_list + _S_freelist_index(__n);
_Obj* __q = (_Obj*)__p;
// acquire lock
ifndef _NOTHREADS
/*REFERENCED*/
_Lock __lock_instance;
endif /* _NOTHREADS */
__q -> _M_free_list_link = *__my_free_list;
*__my_free_list = __q;
// lock is released here
}
}
对于指针的自增行为,要迎合ANSI C 的规范。在ANSI C中void指针不能自增的,这种行为是一种非法行为,因为未知void的大小。
#include <iostream>
int main(int argc, char* argv[])
{
int i = 0;
void *p;
int *pint;
int *pint1;
pint = &i;
p = pint;
std::cout << pint << std::endl;
pint++;
std::cout << pint << std::endl;
std::cout << p << std::endl;
pint1 = (int *)p;
std::cout << pint1 << std::endl;
return 0;
}
运行的结果:
文献参考:
1. 《C++ primer》和《C语言程序设计》
2.http://wenku.baidu.com/view/22c4b8d86f1aff00bed51edc.html这篇文章很出名啊,很多void的文章都是转载这一篇文章的。