C/C++语言中的void及void指针总结

来源:互联网 发布:淘宝直播的东西能买吗 编辑:程序博客网 时间:2024/05/17 01:39

一、void 和 void* 含义

      void的字面意思是“无类型”,void *则为“无类型指针”,void *可以指向任何类型的数据。

      对于void,如果定义void  a;是会编译出错的(vc6下得到:error C2182: 'a' : illegal use of type 'void',vs08中: error C2182: “a”: 非法使用“void”类型)

       对于void*,任何类型的指针都可以直接赋值给它,无需进行强制类型转换。

[c-sharp] view plaincopy
  1. void *p1;  
  2. int *p2;  
  3. p1 = p2;  
 这样是正确的,不过不能将int*转换为void*

二、我们在什么地方能用到void和void*

1、对于void,发挥作用的有两个地方:一是对函数返回值的限定,二是对函数参数的限定。下面举例说明:

(林锐的《高质量c++编程指南》上有以下3个对void和void*的使用的类似示范,即,如没有参数,一定要写明void;如没有返回值,一定标注;如果函数参数可以为任意类型指针,声明函数参数为void*)

1)对于返回值的限定

[c-sharp] view plaincopy
  1. #include "stdio.h"  
  2. add ( int a, int b )  
  3. {  
  4.     return a + b;  
  5. }  
  6. int main(int argc, char* argv[])  
  7. {  
  8.     printf ( "2 + 3 = %d /n ", add ( 2, 3) );  
  9.     return 0;  
  10. }  

     上述程序,在C语言中运行是没有任何问题的,因为c语言中,函数如果没有返回值限定,则编译器默认返回为int来处理。虽然看起来会以为返回void。

     但是在c++中,类似代码:

[c-sharp] view plaincopy
  1. #include <iostream>  
  2. using namespace std;  
  3. add ( int a, int b )  
  4. {  
  5.     return a + b;  
  6. }  
  7. int main(int argc, char* argv[])  
  8. {  
  9.     cout << "2 + 3 = "<<  add ( 2, 3) << endl;  
  10.     return 0;  
  11. }  
 

     在vc6中编译依旧没有问题的,但是在vs08中测试,会得到错误:error C4430: 缺少类型说明符 - 假定为 int;在gcc下编译会出错:error: ISO C++ forbids declaration of 'add' with no type

     这里需要注意的是: C++ 不支持默认 int   因为,C++语言有很严格的类型安全检查,不允许函数不加类型声明的情况发生。因此,为了避免混乱,如果函数没有返回值,一定要声明为void类型。

     说到返回值,顺便提一下,在C++中对函数的重载,是不能通过返回值实现的,因为如同这个示范程序,调用add函数而忽略了其返回值,也就是使用了函数的副作用。

2)对参数的限定

[c-sharp] view plaincopy
  1. #include "stdio.h"  
  2. fun()  
  3. {  
  4.     return 1;  
  5. }  
  6. int main()  
  7. {  
  8.     printf("%d/n",fun(2));  
  9.     return 0;  
  10. }  
 

   说明,C语言中,可以给无参数的函数传送任意类型的参数,当然,这不安全(C99以后C语言有没有改进不知)

   而在c++中,会得到提示错误:error C2660: 'fun' : function does not take 1 parameters(vc6下)或 error: too many arguments to function 'int fun()'(gcc下)

   所以,无论在C还是C++中,若函数不接受任何参数,一定要指明参数为void。

2、void*

    对于void*,也许最常见的应该是库函数吧,像memset,malloc,memcopy。

    内存操作函数memcpy和memset的函数原型分别为:

    void * memcpy(void *dest, const void *src, size_t len);
    void * memset ( void * buffer, int c, size_t num );

    这样,任何类型的指针都可以传入memcpy和memset中,这也真实地体现了内存操作函数的意义,因为它操作的对象仅仅是一片内存,而不论这片内存是什么类型

    malloc原型如下:

 

    extern void *malloc(unsigned int num_bytes);

    对于malloc,函数可以保证返回的内存是地址对齐的(怎么保证的楼主也不知道,《linux程序设计(第4版)》217页描述,待查证),所以,它可以被转换为任何类型的指针。

 

 

    有没有觉得库函数的设计者的确很有远见啊,哈哈

 

3、总结

     对于小小的void和void*,其实还是蛮有学问的,从中,可以看到操作的不断严谨,可以看到设计者的远见,也更提醒我们啊,coding的时候,要尽可能的严密啊。正好碰到了,搜资料,总结然后敲字于此,以备忘,同时,更希望对大家有用。

 

 

参考网址:http://developer.51cto.com/art/200510/9059.htm

原创粉丝点击