void *p1; int *p2; … p1 = p2;虽然如此,但这并不意味着可以无需任何强制类型转换就将 void 指针直接赋给其他类型的指针,因为“空类型”可以包容“有类型”,而“有类型”则不能包容“空类型”。正如我们可以说“男人和女人都是人”,但不能说“人是男人”或者“人是女人”一样。因此,下面的示例代码将编译出错,如果在 VC++2010 中,将提示“a value of type"void*"cannot be assigned to an entity of type"int*"”的错误信息。
void *p1; int *p2; … p2 = p1;由此可见,要将 void 指针赋值给其他类型的指针,必须进行强制类型转换。如下面的示例代码所示:
void *p1; int *p2; … p2 = (int*)p1;
char a[20]="qwertyuiopasdfghjkl";
int *p=(int *)a;
p++;
printf("%s", p);
在上面的示例代码中,指针变量 p 的类型是“int*”,指向的类型是 int,被初始化为指向整型变量 a。void * p; p++; // ANSI:错误 p+= 1; // ANSI:错误上面的代码在 VC++2010 中将提示“expression must be a pointer to a complete object type”的错误信息。
void * p; p++; // GUN:正确 p+=1; // GUN:正确下面的示例代码演示了在 GCC 中执行对 void 指针的自增操作:
#include <stdio.h>
int main(void)
{
void * p="ILoveC";
p++;
printf("%s\n", p);
}
运行结果为:
void *memset(void *buffer, int b, size_t size)
{
assert(buffer!=NULL);
char* retAddr = (char*)buffer;
while (size--> 0)
{
*(retAddr++) = (char)b;
}
return retAddr;
}
void *memcpy (void *dst, const void *src, size_t size)
{
assert((dst!=NULL) && (src!=NULL));
char *temp_dest = (char *)dst;
char *temp_src = (char *)src;
char* retAddr = temp_dest;
size_t i = 0;
/* 解决数据区重叠问题*/
if ((retAddr>temp_src) && (retAddr<(temp_src+size)))
{
for (i=size-1; i>=0; i--)
{
*(temp_dest++) = *(temp_src++);
}
}
else
{
for (i=0; i<size; i++)
{
*(temp_dest++) = *(temp_src++);
}
}
*(retAddr+size)='\0';
return retAddr;
}
这样,任何类型的指针都可以传入 memcpy 函数和 memset 函数中,这也真实地体现了内存操作函数的意义,因为它操作的对象仅仅是一片内存,而不论这片内存是什么类型。memcpy 函数的调用示例如下面的代码所示:
char buf[]="abcdefg";
// buf+2(从c开始,长度3个,即cde)
memcpy(buf, buf+2 ,3);
printf("%s\n", buf);
或者进行如下形式的调用:int dst[100]; int src[100]; memcpy(dst, src, 100*sizeof(int));因为参数类型是 void*,所以上面的调用都是正确的。现在假设 memcpy 函数的参数类型不是 void*,而是 char*,如下面的代码所示:
char *memcpy(char* dst, const char* src, size_t size)
{
assert((dst !=NULL) && (src != NULL));
char *retAddr = dst;
size_t i = 0;
if ((retAddr>src) && (retAddr<(src+size)))
{
for (i=size-1; i>=0; i--)
{
*(dst++)= *(src++);
}
}
else
{
for (i=0; i<size; i++)
{
*(dst++) = *(src++);
}
}
*(retAddr+size)='\0';
return retAddr;
}
现在继续执行如下形式的调用:int dst[100]; int src[100]; memcpy(dst, src, 100*sizeof(int));由于类型不匹配,编译器就会报错。由此可见,这样的函数同时也失去了通用性。
版权说明:Copyright © 广州松河信息科技有限公司 2005-2025 版权所有 粤ICP备16019765号
广州松河信息科技有限公司 版权所有