我们以前在拷贝一个字符串时只想到过strcpy()函数拷贝,但是这个函数在使用时存在一定的缺点,一方面它只能用来拷贝字符串并不能拷贝其他类型的数据,另一方面它只有在遇到'\0'时才结束拷贝,所以容易溢出。所以,就引入memcpy()这个内存操作函数。首先,先看一下二者的区别:
memcpy:
1.函数原型:void *memcpy( void *dest, const void *src, size_t count );
2.理解:此函数在进行拷贝时,所给出的两块内存必须是不相关联的
如果给一个类型已经给定的数组,例如 int arr1[]={1,2,3,4,5,6,7,8};要求将其复制到数组 int arr2[] 中去,我们一定想到的是下面这种办法:
int *my_memcpy(int *dest,const int *src,int sz)
{
int *pdest = dest;
while(sz--)
{
*pdest = *src;
src++;
pdest++;
}
return dest;
}
试想想,假如就给了上边这段代码,如果要拷贝的是 char 型的字符串呢?!或者其他类型的数呢?!那这段程序就得一直被修改,这样就特别麻烦,因此,在此代码的基础上做一些修改就可以打破这样的局限性
void *my_memcpy(void *dest,const void *src,int sz)
{
char *pdest = (char*)dest;
const char *psrc = (const char *)src;
assert(dest);
assert(src);
while(sz--)
{
*pdest = *psrc;
psrc++;
pdest++;
}
return dest;
}
显然这是将类型改为了 void* 型的,这样 void* 类型的指针就可以指向任意类型的指针,在函数内部将其强制类型转换为 char* 类型同样也是为了程序的实用性,使其在复制时是一个字节一个字节地拷贝
memmove:
1.函数原型: void *memmove( void *dest, const void *src, size_t count );
2.理解:将src所指向的字符串拷贝 count 个到 dest 所指向的字符串中,这两块内存可以是相关联的,也可以是 不相关联的。
讨论内存相关联的情况———假设给定数组 int arr1[ ]={1,2,3,4,5,6,7,8},要将其输出为12123678,即将123拷贝到从2 开始的位置:
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
void *my_memmove(void *dest,const void *src,int count)
{
char *pdest = (char *)dest;
char *psrc = (char *)src;
assert(dest);
assert(src);
if((pdest>psrc)&&(pdest<(psrc+count))) //dest指向于src和src+count的中间
{
while(count--)
{
*(pdest+count) = *(psrc+count);
//pdest--;
//psrc--;
}
}
else
{
while(count--)
{
*pdest++ = *psrc++;
}
}
return dest;
}
int main()
{
int arr1[]={1,2,3,4,5,6,7,8};
int sz = sizeof(arr1);
int i = 0;
my_memmove(arr1+2,arr1,3*sizeof(int));
for(i=0; i<sizeof(arr1)/sizeof(arr1[0]); i++)
{
printf("%d ",arr1[i]);
}
system("pause");
return 0;
}
这段代码同样存在一定的局限性,同样也可以将指针类型改为void* 类型,但需注意的是 void* 类型的指针不能自加自减,也不能解引用,所以必须将其强制类型转换
memset
:
1.函数原型:void *memset( void *dest, intc, size_tcount );
2.理解:此函数是对 dest 所指向的某一块内存的前 count 个字节初始化为c对应的ASCCII值
void *my_memset(void *dest,int ch,size_t count)
{
char *pdest = (char *)dest;
while(count--)
{
*pdest = ch;
pdest++;
}
return dest;
}