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;
} 

运行结果太棒了

20RQ76LKBLX5_Q_thumb

在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;
} 

运行结果哭泣的脸

7A8_IPQDX6VMHP7O5V2_thumb

    恶魔在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;
} 

运行的结果:

9OV3PPIYTPM41KMFY_thumb

文献参考:

1. 《C++ primer》和《C语言程序设计》

2.http://wenku.baidu.com/view/22c4b8d86f1aff00bed51edc.html这篇文章很出名啊太阳,很多void的文章都是转载这一篇文章的。

posted @ 2012-02-22 14:55  云端小飞象cg  阅读(7270)  评论(6编辑  收藏  举报