`

C语言中void*详解及应用(1)

阅读更多

void的含义:

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

void几乎只有“注释”和限制程序的作用,因为从来没有人会定义一个void变量,让我们试着来定义:

void a;

这行语句编译时会出错,提示“illegal use of type 'void'”。即使void a的编译不会出错,它也没有任何实际意义。

    众所周知,如果指针p1和p2的类型相同,那么我们可以直接在p1和p2间互相赋值;如果p1和p2指向不同的数据类型,则必须使用强制类型转换运算符把赋值运算符右边的指针类型转换为左边指针的类型。

 float *p1;
 int *p2;
 p1 = p2;
 //其中p1 = p2语句会编译出错,
 //提示“'=' : cannot convert from 'int *' to 'float *'”,必须改为:
 p1 = (float *)p2;

 而void *则不同,任何类型的指针都可以直接赋值给它,无需进行强制类型转换:

void *p1;
 int *p2;
 p1 = p2;

但这并不意味着,void *也可以无需强制类型转换地赋给其它类型的指针。因为“无类型”可以包容“有类型”,而“有类型”则不能包容“无类型”。

 小心使用void指针类型:

按照ANSI(American National Standards Institute)标准,不能对void指针进行算法操作,即下列操作都是不合法的:

void * pvoid;
pvoid++; //ANSI:错误
pvoid += 1; //ANSI:错误
//ANSI标准之所以这样认定,是因为它坚持:进行算法操作的指针必须是确定知道其指向数据类型大小的。
//例如:
int *pint;
pint++; //ANSI:正确
pint++的结果是使其增大sizeof(int)。

 但是GNU则不这么认定,它指定void *的算法操作与char *一致。因此下列语句在GNU编译器中皆正确: 

pvoid++; //GNU:正确
pvoid += 1; //GNU:正确
pvoid++的执行结果是其增大了1。

 在实际的程序设计中,为迎合ANSI标准,并提高程序的可移植性,我们可以这样编写实现同样功能的代码:

void * pvoid;
 (char *)pvoid++; //ANSI:正确;GNU:正确
 (char *)pvoid += 1; //ANSI:错误;GNU:正确

GNU和ANSI还有一些区别,总体而言,GNU较ANSI更“开放”,提供了对更多语法的支持。但是我们在真实设计时,还是应该尽可能地迎合ANSI标准。 

 如果函数的参数可以是任意类型指针,那么应声明其参数为void *

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

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

  这样,任何类型的指针都可以传入memcpy和memset中,这也真实地体现了内存操作函数的意义,因为它操作的对象仅仅是一片内存,而不论这片内存是什么类型。如果memcpy和memset的参数类型不是void *,而是char *,那才叫真的奇怪了!这样的memcpy和memset明显不是一个“纯粹的,脱离低级趣味的”函数!

 void的出现只是为了一种抽象的需要,如果你正确地理解了面向对象中“抽象基类”的概念,也很容易理解void数据类型。正如不能给抽象基类定义一个实例,我们也不能定义一个void(让我们类比的称void为“抽象数据类型”)变量。

分享到:
评论

相关推荐

    C语言中memcpy 函数的用法详解

    C语言中memcpy 函数的用法详解 memcpy(内存拷贝函数) c和c++使用的内存拷贝函数,memcpy函数的功能是从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中。 void* memcpy(void* ...

    C语言-字符串函数大全和详解

    c语言字符串函数详解 void *memset(void *dest, int c, size_t count); 将dest前面count个字符置为字符c. 返回dest的值.

    C语言memset函数使用方法详解

    C语言memset函数使用方法详解 一。函数原形 void * memset(void*s, int ch,size_t n) 二。函数作用 将以s内存地址为首的连续n个字节的内容置成ch,一般用来对大量结构体和数组进行清零 三。常见错误 1.搞反...

    C语言中指针 int *p=0;和int *p;*p=0;和”&“的关系和区别详解

    初学者在学习C语言的时候,最头疼的可能就是指针,话不多说。让我们直接进入正题 直接上代码 int main(void) { int *p = 0; printf(%d, *p); system(pause); return 0; } 直接运行,好了,程序是不是...

    void 指针详解(用法、注意事项等等 )

    许多初学者对C/C++语言中的void及void指针类型不甚理解,因此在使用上出现了一些错误。本文将对void关键字的深刻含义进行解说,并详述void及void指针类型的使用方法与技巧。

    快速排序法C语言详解

    void qsort(int arr[],int left,int right) //qsort()函数实现快速排序,并且是递归调用,而且,递归调用qsort()函数本身两次,因为要对中值两边的 { //部分分别进行排序。arr是待排序的数组名,left是排序的左边界,...

    高级C语言详解

    1. C 语言中的指针和内存泄漏 5 2. C语言难点分析整理 10 3. C语言难点 18 4. C/C++实现冒泡排序算法 32 5. C++中指针和引用的区别 35 6. const char*, char const*, char*const的区别 36 7. C中可变参数函数实现 38...

    C语言中qsort函数的用法实例详解

    C语言中qsort函数的用法实例详解 快速排序是一种用的最多的排序算法,在C语言的标准库中也有快速排序的函数,下面说一下详细用法。 qsort函数包含在中 qsort函数声明如下: void qsort(void * base,size_t nmemb...

    C语言中使用快速排序算法对元素排序的实例详解

    int comp1(const void *x,const void *y) { return *(int *)x - *(int *)y; } //从大到小排序 int comp2(const void *x,const void *y) { return *(int *)y - *(int *)x; } void main() { int arr[SIZE];

    C语言绘图函数使用方法详解

    C语言图形函数 Turbo C提供了非常丰富的图形函数, 所有图形函数的原型均在graphics. h 中, 本节主要介绍图形模式的初始化、独立图形程序的建立、基本图形功能、图 形窗口以及图形模式下的文本输出等函数。另外, ...

    C语言动态内存分配的详解

    C语言动态内存分配的详解 1.为什么使用动态内存分配 数组在使用的时候可能造成内存浪费,使用动态内存分配可以解决这个问题。 2. malloc和free C函数库提供了两个函数,malloc和free,分别用于执行动态内存分配和...

    c语言难点分析整理,C语言

    1. C 语言中的指针和内存泄漏 5 2. C语言难点分析整理 10 3. C语言难点 18 4. C/C++实现冒泡排序算法 32 5. C++中指针和引用的区别 35 6. const char*, char const*, char*const的区别 36 7. C中可变参数函数实现 38...

    c语言 malloc函数详解

    谈到malloc函数相信学过c语言的人都很熟悉,但是malloc底层到底做了什么又有多少人知道。 1、关于malloc相关的几个函数 关于malloc我们进入Linux man一下就会得到如下结果:   也可以这样认为(window下)...

    C语言 文件操作解析详解及实例代码

    C语言文件操作解析  在文件操作中除了打开操作以及读写操作,还有几种比较常见的操作。下面介绍一下这些操作中涉及到的函数。 一.移动位置指针的函数  rewind函数和fseek函数,这两个函数的原型是:  void rewind...

    C语言中堆空间的生成与释放详解

     功能:在堆中分配 size 字节的连续空间 参数:size_字节数 返回值:成功返回分配空间的首地址,失败返回 NULL free void free(void *ptr); 功能:释放由 malloc、calloc、realloc 分配的空间 参数:ptr_空间...

    C语言自增自减运算符深入剖析

    C语言的自增++,自减--运算符对于初学者来说一直都是个难题,甚至很多老手也会产生困惑,最近我在网上看到一个问题:  #include  void main() /*主函数*/  {  int a,b,c,d;  a=5;  b=5;  c=...

    51单片机DS18B20温度计C语言程序(附详解)

    //0-F数码管的编码(共阳极)unsigned char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//0-9数码管的编码(共阳极), 带小数点unsigned char code ...

    详解C语言中的memset()函数

    C语言memset()函数:将内存的前n个字节设置为特定的值 头文件: #include memset() 函数用来将指定内存的前n个字节设置为特定的值,其原型为: void * memset( void * ptr, int value, size_t num ); 参数说明...

    史上最强的C语言资料

    1. C 语言中的指针和内存泄漏 5 2. C语言难点分析整理 10 3. C语言难点 18 4. C/C++实现冒泡排序算法 32 5. C++中指针和引用的区别 35 6. const char*, char const*, char*const的区别 36 7. C中可变参数函数实现 38...

    几道华为经典C语言面试题

    华为面试 C语言面试 C语言面试详解 1、找错 void test1() { char string[10]; char* str1="0123456789"; strcpy(string, str1); } 这里string数组越界,因为字符串长度为10,还有一个结束符‘\0’。所以总共有...

Global site tag (gtag.js) - Google Analytics