Chinaunix首页 | 论坛 | 博客
  • 博客访问: 157745
  • 博文数量: 31
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 360
  • 用 户 组: 普通用户
  • 注册时间: 2017-02-28 08:37
个人简介

没有绝活,怎能风骚.....

文章分类

全部博文(31)

文章存档

2017年(31)

我的朋友

分类: C/C++

2017-04-07 14:32:07

转载自:,只是根据自己的理解,对部分内容作了修改。
1.void的含义
    void即“无类型”,void*则为“无类型指针”,可以指向任何数据类型。

2.void指针使用规范
    ①void指针可以指向任意类型的数据,亦即可用任意数据类型的指针对void指针赋值。
        例如:int *p_int;
                  void *p_void;
                  p_void = p_int; //不能p_int = p_void;
        如果要将p_void赋给其他类型的指针,则需要强制类型转换,如:p_int = (int *)p_void;  
    ②在ANSI_C标准中,不允许void指针进行算术运算,如p_void ++;或 p_void += 1等;而在GNU中则允许,因为缺省情况下,GUN认为void *与char *一样。sizeof(*p_void) == sizeof(char)。

3.void的作用
    ①对函数返回的限定。
        当函数不需要返回值时,必须使用void限定。如:void func(int,int);
    ②对函数参数的限定。
        当函数不允许接收参数时,必须使用void限定。如:void func(void);
    由于void指针可以指向任意类型的数据,即可用任意数据类型的指针对void指针赋值,因此还可以用void指针来作为函数形参,这样函数就可以接收任意数据类型的指针作为参数。
    例如:void *memcpy(void *dest,const void *src,size_t count);
              void *memset(void *buffer,int c,size_t n);

4.void及void指针类型的使用方法与技巧
    ①小心使用void指针类型
        按照ANSI标准,不能对void指针进行算法操作,即下列操作都不合法:
        void *p_void;
        p_void ++;//ANSI:错误
        p_void += 1;//ANSI:错误
        ANSI标准之所以这样认定,是因为它坚持:进行算法操作的指针必须是确定指定其指向数据类型大小的。
        如:int *p_int;
               p_int ++;//ANSI:正确
               p_int ++的结果是地址偏移sizeof(int)。
        大名鼎鼎的GNU则不这么认定,它指定void*的算法操作与char*一致。因此下列语句在GNU编译器中皆正确:
               p_void ++;//GNU:正确
               p_void += 1;//GNU:正确
               p_void ++的执行结果是地址偏移1。
        在实际的程序设计中,为迎合ANSI标准,并提高程序的可移植性,我们可以这样编写实现同样功能的代码:
        void *p_void;
        (char *)p_void ++;//ANSI:正确;GNU:正确
        (char *)p_void += 1;//ANSI:错误,GNU:正确
        GNU和ANSI还有一些区别,总体而言,GNU较ANSI更“开放”,提供了对更多语法的支持。但是我们在真实设计时,还是应该尽可能地迎合ANSI标准。
    ②如果函数的参数可以是任意类型指针,那么应声明其参数为void*
        典型的如内存操作函数memcpy和memset的函数原型分别为:
        void* memcpy(void* dest,const void* src,size_t count);   
        void* memset(void* buffer,int c,size_t n);
        这样,任何类型的指针都可传入memcpy和memset中,这也真实地体现了内存操作函数的意义,因为它操作的对象仅仅是一片内存,而不论这片内存时什么类型。如果memcpy和memset的参数类型不是void*, 而是char*,这才叫真的奇怪,这样的memcpy和memset明显不是一个“通用的”、“符合大众需求的”函数。
    代码示例1:
    int array_int[100];
    memset(array_int,0,100*sizeof(int));//将array_int清0
    代码示例2:
    int array_int1[100],array_int2[200];
    memcpy(array_int1,array_int2,100*sizeof(int));//将array_int2拷贝给array_int1
    其实,memcpy和memset函数返回的也是void*类型,标准库函数的编写者是多么的有先见之明。
    ③void不能代表一个真实的变量
        下面代码都企图让void代表一个真实的变量,因此都是错误的代码:
         void a;//错误
         function(void a);//错误
    其实void体现了一种抽象,这个世界上的变量都是有“类型”的,void的出现只是为了一种抽象的需要,如果你正确理解了面向对象中的“抽象基类”的概念,就很容易理解void数据类型。正如不能给抽象基类定义一个实例,我们也不能定义一个void(可以类比地称void为“抽象数据类型”)变量。
阅读(1129) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~