C语言void及void指针含义的浓厚分析

http://blog.csdn.net/geekcome/article/details/6249151


void**的含义**

void即“无类型”,void *虽说也“无类型指针”,可以对任何数据类型。
void**指南针动标准①void指针可以对任意档次的数目,亦即可用任意数据类型的指针指向void指针赋值。例如: int * pint; void *pvoid; pvoid = pint; /*
不过不能够
pint= pvoid; */
如果如拿pvoid赋给任何类指针,则用强制类型转换如:pint= (int *)pvoid;
②以ANSIC标准被,不同意对void指针进行算术运算而pvoid++或pvoid+=1等,而在GNU中虽然允许,因为于短缺省气象下,GNU认为void *与char *一样。sizeof(*pvoid )== sizeof( char).
void**的作用①针对函数返回的限量。 ②对函数参数的限量。当函数不欲返回值时,必须动void限定。例如: void func(int, int); 当函数不允许受参数时,必须采取void限定。例如: int func(void)。
由void指针可以本着任意档次的数,亦即可用任意数据类型的指针指向void指针赋值,因此还可以就此void指针来作函数形参,这样函数就足以接受任意数据类型的指针作为参数。例如: void * memcpy( void *dest, const void *src,

size_t len ); void * memset( void * buffer, int c, size_t num);

1. 综述

 

成百上千新家针对C/C++语言中的void及void指针类型不甚清楚,因此当使用上起了片谬误。本文将本着void关键字之深刻含义进行解释,并详述void及void指针类型的行使方式与技能。

2.void的含义

  void**的字面意思是“无类型”,void*尽管如此也“无类型指针”,void*可针对任何类型的数。void几只有“注释”和限制程序的作用,因为根本没人会见定义一个void变量,让咱们试试着来定义:*void a;   这行语句编译时会拧,提示“illegal use of
type’void’”。不过,即使voida的编译不会见错,它呢没有其余实际意义。  void真正发挥的来意在于:  (1)对函数返回的克;  (2)对函数参数的克。   众所周知,如果指针p1和p2的档次相同,那么我们得以直接在p1和p2间互为赋值;如果p1和p2指于不同的数据类型,则要下强制类型转换运算符把赋值运算符右边的指针类型转换为左指针的门类。  例如: float \
p1; in t* p2; p1 = p2;
  其中p1 = p2告知句子会编译出错,提示“’=’:cannotconvertfrom’int *’to’float
*’”,必须反也: p1=(float*)p2; 而void*尽管如此不同,任何项目的指针都可以直接赋值给其,无需进行强制类型转换: void * p1; int * p2; p1 = p2;
  但这并无表示,void*也可以不用强制类型转换地给予给其它品类的指针。因为“无类型”可以容纳“有路”,而“有路”则未克包容“无类型”。道理很粗略,我们可说“男人和家还是人数”,但非克说“人是丈夫”或者“人是家”。下面的话语编译出错: void * p1; int * p2; p2 =
p1;

 

  提示“’=’:cannotconvertfrom’void*’to’int*’”。

3.void的使用

  下面让有void关键字之施用规则:  规则一样比方函数没有回到值,那么应声明也void类型  在C语言中,凡不加以返回值类型限定的函数,就会给编译器作为返回整型值处理。但是过多程序员却误以为其也void类型。例如: add(inta,intb) {
return a+b; } int main(int argc,char * argv[]) {
printf(/”2+3=%d/”,add(2,3)); }   程序运行的结果为出口:  2+3=5
  这说明非加返回值说明的函数的确为int函数。  林锐博士《高质量C/C++编程》中干:“C++语言有好严峻的类安全检查,不允上述情况(指函数不加类型声明)发生”。可是编译器并不一定这么肯定,譬如当VisualC++6.0中上述add函数的编译无错也无警告且运行对,所以未可知寄希望于编译器会做严格的类别检查。  因此,为了避免混乱,我们于编写C/C++程序时,对于其它函数都必须一个免漏地指定其类别。如果函数没有回值,一定要是声明也void类型。这既是程序可以可读性的用,也是编程规范性的求。另外,加上void类型声明后,也可以表达代码的“自注释”作用。代码的“自注释”即代码能友好注释自己。
[Page]
规则二假设果函数无参数,那么应声明其参数为void
  在C++语言中声称一个如此的函数: int
function(void) { return1; }   则开展下的调用是不合法的: function(2);
  因为在C++中,函数参数为void的意是此函数不受任何参数。我们以TurboC2.0被编译:
#include”stdio.h” fun() { return1; } main() { printf(/”%d/”,fun(2));
getchar(); }   编译正确且输出1,这说明,在C语言中,可以为无参数的函数传送任意档次的参数,但是当C++编译器中编译同样的代码则会错。在C++中,不可知向无论参数的函数传送任何参数,出错提示“’fun’:functiondoesnottake1parameters”。  所以,无论在C还是C++中,若函数不受其他参数,一定要是指明参数为void。  规则三小心使用void指针类型  按照ANSI(AmericanNationalStandardsInstitute)标准,不可知针对void指针进行算法操作,即下列操作都是匪合法的: void * pvoid;
pvoid ++;//ANSI:错误 pvoid +=
1;//ANSI:错误
ANSI标准之所以如此认定,是为它坚持:进行算法操作的指针必须是规定知道其对数据类型大小的。例如: int * pint;
pint ++;//ANSI:正确pint++的结果是若其增大sizeof(int)。但是大名鼎鼎的GNU(GNU’sNotUnix的缩写)则免这样肯定,它指定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,constvoid*src,size_tlen);

 

void *
memset(void*buffer,intc,size_tnum);

  这样,任何项目的指针都好流传memcpy和memset中,这也真正地反映了内存操作函数的义,因为她操作的目标仅是如出一辙切开内存,而不论是这片内存是什么种。如果
memcpy和memset的参数类型不是void*,而是char*,那才给真正奇怪了!这样的memcpy和memset明显不是一个“纯粹的,脱离低级趣味的”函数!

下面的代码执行正确: //示例:memset接受任意档次指针 int intarray[100];[Page]
memset(intarray,0,100*sizeof(int));//将intarray清0 //示例:memcpy接受任意档次指针 int intarray1[100],intarray2[100];
memcpy(intarray1,intarray2,100*sizeof(int));//将intarray2拷贝给intarray1   有趣的凡,memcpy及memset函数回的也罢是void*品类,标准库函数的编辑是何等地具有学问啊!  规则五void不能够代表一个真实的变量  下面代码都企图吃void代表一个真的变量,因此还是一无是处的代码: void a;//错误 function(void a);//错误  void体现了平栽浮泛,这个世界上之变量都是“有项目”的,譬如一个丁未是老公不怕是老婆(还有人妖?)。  void的出现就是为着一种浮泛的需,如果你不利地懂得了面向对象中“抽象基类”的概念,也特别容易了解void数据类型。正使非可知让抽象基类定义一个实例,我们为无能够定义一个void(让咱类比的如void为“抽象数据类型”)变量。

4.总结

  小小的void蕴藏在老丰富的筹划哲学,作为一如既往叫作先后设计人员,对题目进行特别一个层次之思必然要我们受益匪浅。