1)可以用任何类型的指针对 void 指针进行赋值
由于void 指针没有特定的类型,因此可以指向任何类型的数据。因此他可以指向任何类型的数据。也就是说,任何类型的指针都可以直接赋值给 void 指针,而无需进行其他相关的强制类型转换。
例如:
double d = 1.54;
void * p = & d;
2)void 指针不可以直接赋值给其它类型的指针
因为 “空类型” 可以包容 “有类型”,而 “ 有类型” 则不能包容 “空类型”。
由此可见,要将 void 指针赋值给其他类型的指针,必须进行强制类型转换。如:
1 void * p1; 2 int * p2; 3 . . . 4 p2 = (int *)p1;
3)避免对 void 指针进行算术操作
ANSI C 标准规定,进行算法操作的指针必须确定知道其指向数据类型大小,也就是说必须知道内存目的地址的确切值。
1 char a[20]="qwertyuiopasdfghjkl"; 2 int *p=(int *)a; 3 p++; 4 printf("%s", p); // tyuiopasdfghjkl
p++;一步前进了sizeof(int)=4 个字节,而类型为char,sizeof(char)=1
对于 void 指针,编译器并不知道所指对象的大小,所以对 void 指针进行算术操作都是不合法的,如下面的示例代码所示:
1 void * p; 2 p++; // ANSI:错误 3 p+= 1; // ANSI:错误
但值得注意的是,GNU 则不这么认为,它指定“void*”的算法操作与“char*”一致。因此下列语句在 GNU 编译器中都是正确的:
1 void * p; 2 p++; // GUN:正确 3 p+=1; // GUN:正确
下面代码演示了在 GCC中 执行对 void 指针的自增操作:
1 #include <stdio.h> 2 int main(void) 3 { 4 void * p="ILoveC"; 5 p++; 6 printf("%s\n", p); //输出:LoveC 7 }
由此可见,GNU 和 ANSI 还存在着一些区别,相比之下,GNU 较 ANSI 更“开放”,提供了对更多语法的支持。但是在真实的设计环境中,还是应该尽可能符合 ANSI 标准,尽量避免对 void 指针进行算术操作。
4)应用:内存操作函数
根据 1)中的内容,void 指针可以指向任意类型的数据,同时任何类型的指针都可以直接赋值给 void 指针,而无需进行其他相关的强制类型转换。因此,在编程中,如果函数的参数可以是任意类型指针,那么应该使用 void 指针作为函数的形参,这样函数就可以接受任意数据类型的指针作为参数。
1 void *memset(void *buffer, int b, size_t size) 2 { 3 assert(buffer!=NULL); 4 char* retAddr = (char*)buffer; 5 while (size-- > 0) 6 { 7 *(retAddr++) = (char)b; 8 } 9 return retAddr; 10 } 11 12 13 void *memcpy (void *dst, const void *src, size_t size) 14 { 15 assert((dst!=NULL) && (src!=NULL)); 16 char *temp_dest = (char *)dst; 17 char *temp_src = (char *)src; 18 char* retAddr = temp_dest; 19 size_t i = 0; 20 /* 解决数据区重叠问题*/ 21 if ((retAddr>temp_src) && (retAddr<(temp_src+size))) 22 { 23 for (i=size-1; i>=0; i--) 24 { 25 *(temp_dest++) = *(temp_src++); 26 } 27 } 28 else 29 { 30 for (i=0; i<size; i++) 31 { 32 *(temp_dest++) = *(temp_src++); 33 } 34 } 35 *(retAddr+size)='\0'; 36 return retAddr; 37 }
来源:https://www.cnblogs.com/guoyujiang/p/12294653.html