【内存操作函数】

字符串操作函数中有一个strcpy的函数,它可以拷贝字符类型,那么有没有不关心类型的函数呢?这个,当然是有滴,大师们早就将他们写到库里面了。


1.memcpy() 用来复制内存,其原型为:
    void * memcpy ( void * dest, const void * src, size_t num );

memcpy() 会复制 src 所指的内存内容的前 num 个字节到 dest 所指的内存地址上。

memcpy() 并不关心被复制的数据类型,也就是说它可以操作任意类型,只是逐字节地进行复制,这给函数的使用带来了很大的灵活性,可以面向任何数据类型进行复制。

需要注意的是:


>>1.dest 指针要分配足够的空间,也即大于等于 num 字节的空间。如果没有分配空间,会出现断错误。

>>2.dest 和 src 所指的内存空间不能重叠(如果发生了重叠,使用 memmove()会更加安全)。


与 strcpy() 不同的是,memcpy() 会完整的复制 num 个字节,不会因为遇到“\0”而结束。

【返回值】返回指向 dest 的指针。注意返回的指针类型是 void,使用时一般要进行强制类型转换。


【函数实现】

#include <stdio.h>
#include <string.h>
#define MAX 20
void* my_memcpy(void *dest,const void *src,size_t count)
{
     int *buf1=(int *)dest;
     int *buf2=(int *)src;
     int *pret=(int *)dest;
     while (count--)
     {
          *buf1=*buf2;
          buf1++;
          buf2++;
     }
     return pret;
}
int main()
{
     int arr[MAX]={0};
     int brr[5]={1,2,3,4,5};
     int size=sizeof(brr)/sizeof(brr[0]);
     int i=0;
     my_memcpy(arr,brr,size);
     for (i=0;i<MAX;i++)
     {
         printf("%d ",arr[i]);
     }
     printf("\n");
     return 0;
}

结果:

wKiom1Zeq2WwjIaEAAAQOTtxaAg314.png

这个就将原数组中的0一个不漏的打印出来了,好神奇_^_^_

有了这个函数,就解决了一部分拷贝的问题,为什么说一部分呢,接下来,听我慢慢道来。这个时候,我有一个问题,如果我给定一个数组arr[10]={1,2,3,4,5,6,7,8,9,10};我想把它的{5,6,7,8}拷贝到{7,8,9,10}上去最后打印出数组arr结果应该是{1,2,3,4,5,6,5,6,7,8};接下来看代码实现:

#include <stdio.h>

void* my_memcpy(void *dest,const void *src,size_t count)
{
     int *buf1=(int *)dest;
     int *buf2=(int *)src;
     int *p=(int *)dest;
     while (count--)
     {
          *buf1=*buf2;
          buf1++;
          buf2++;
     }
     return p;
}

int main()
{
     int arr[10]={1,2,3,4,5,6,7,8,9,10};
     int i=0;
     my_memcpy(arr+6,arr+4,16);
     for (i=0;i<10;i++)
     {
          printf("%d ",arr[i]);
     }
     printf("\n");
     return 0;
}

结果:

wKioL1ZgHOqC8qtmAAAPfoQWM44855.png

这个结果怎么和预先预测的结果不一样呢_~~_这就是出现上面注意的第二点dest 和 src 所指的内存空间不能重叠,如果出现重叠,就会出现想不到的问题。

wKioL1ZgIkqCfz-cAAAx0wuUGUY848.png


所以此时就要用一个memmove()的函数,他很好的处理了这个问题。


2.memmove() 用来复制内存内容,其原型为:
    void * memmove(void *dest, const void *src, size_t num);

memmove() 与 memcpy() 类似都是用来复制 src 所指的内存内容前 num 个字节到 dest 所指的地址上。不同的是,memmove() 更为灵活,当src 和 dest 所指的内存区域重叠时,memmove() 仍然可以正确的处理.同样是上面的问题,具体看下它的实现:

【函数实现】

#include <stdio.h>

void *my_memmove(void *dest,const void *src,size_t count)
{
     int *buf1=(int *)dest;
     int *buf2=(int *)src;
     int *p=(int *)dest;
     if (buf1>buf2&&buf1<buf2+count)
     {
          while (count--)
          {
               *(buf1+count)=*(buf2+count);
          }
     }
     else
     {
          while (count--)
          {
               *buf1++=*buf2++;
          }
     }
     return p;
}

int main()
{
     int arr[10]={1,2,3,4,5,6,7,8,9,10};
     int i=0;
     my_memmove(arr+6,arr+4,16);
     for (i=0;i<10;i++)
     {
          printf("%d ",arr[i]);
     }
     printf("\n");
     return 0;
}

结果:

wKiom1ZgKCfwEu-8AAAQcnJTsJg461.png

这个结果就和预先猜想的一样了,为什么会一样呢?因为当它处理有重叠时,它在拷贝时,会从后往前复制,就不会干扰到源了,所以结果正确。不重叠时,仍然和memcpy()一样,但效率能比memcpy()

低,因为它在复制之前还要进行判断_^_._^_