memory系列函数对比以及实现

  • 文档内容:
    • memcpy、memmove、memccpy说明、比较
    • memcpy(拷贝)实现
    • memset(设置值)实现
    • memmove(拷贝)实现
    • memccpy(拷贝,遇到设定值终止拷贝)实现

  • memcpy()、 memmove()和memccpy()

    • 这三个函数的功能均是将某个内存块复制到另一个内存块。
      前两个函数的区别在于它们处理内存区域重叠(overlapping)的方式不同。
      第三个函数的功能也是复制内存,但是如果遇到某个特定值时立即停止复制。

    • 对于库函数来说,由于没有办法知道传递给他的内存区域的情况,所以应该使用memmove()函数。
      通过这个函数,可以保证不会出现任何内存块重叠问题。
      而对于应用程序来说,因为代码“知道”两个内存块不会重叠,所以可以安全地使用memcpy()函数。


  • memcpy和memmove()都是C语言中的库函数,在头文件string.h中,作用是拷贝一定长度的内存的内容,原型分别如下:
    • void *memcpy(void *dst, const void *src, size_t count);

    • void *memmove(void *dst, const void *src, size_t count);

    • 他们的作用是一样的,唯一的区别是,当内存发生局部重叠的时候,memmove保证拷贝的结果是正确的,memcpy不保证拷贝的结果的正确。


1043344-20161127174206596-1166586900.jpg

* 第一种情况下,拷贝重叠的区域不会出现问题,内容均可以正确的被拷贝。
* 第二种情况下,问题出现在右边的两个字节,这两个字节的原来的内容首先就被覆盖了,而且没有保存。所以接下来拷贝的时候,拷贝的是已经被覆盖的内容,显然这是有问题的。

* 实际上,memcpy只是memmove的一个子集。
    二者的c语言实现很简单,有兴趣的朋友可以去看看。在实际情况下,这两个函数都是用汇编实现的。

* memmove在copy两个有重叠区域的内存时可以保证copy的正确,而memcopy就不行了,但memcopy比memmove的速度要快一些,如:
char s[] = "1234567890";
char* p1 = s;
char* p2 = s+2;
* memcpy(p2, p1, 5)与memmove(p2, p1, 5)的结果就可能是不同的,memmove()可以将p1的头5个字符"12345"正确拷贝至p2,而memcpy()的结果就不一定正确了

  • memccpy原型:extern void *memccpy(void *dest, void *src, unsigned char ch, unsigned int count);

    • 功能:由src所指内存区域复制不多于count个字节到dest所指内存区域,如果遇到字符ch则停止复制。
    • 说明:返回指向字符ch后的第一个字符的指针,如果src前n个字节中不存在ch则返回NULL。ch被复制。

memcpy函数
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>




void *   mymemcpy(void * _Dst, const void * _Src, unsigned int _Size)
{
    if (_Dst ==NULL  || _Src==NULL)
    {
        return NULL;
    }
    char * ndest = _Dst;
    char *  src = _Src;//之指针类型转换

    for (int i = 0; i < _Size;i++)//循环拷贝
    {
        ndest[i] = src[i];

    }
    return ndest;
}
void *   mynewmemcpy(void * _Dst, const void * _Src, unsigned int _Size)
{
    if (_Dst == NULL || _Src == NULL)
    {
        return NULL;
    }
    int i = 0;

    for (char *dest = _Dst, *src = _Src  ; i< _Size     ; dest++, src++, i++)
    {
        *dest = *src;//指针法

    }
    return _Dst;//C语言注意必须返回




}



void main()
{
    int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    int *p=malloc(sizeof(int )*10);
    mynewmemcpy(p, a, 40);
    //第一个是地址,被拷贝进去的内存地址
    //a用于复制的内存首地址,40长度
    for (int i = 0; i < 10;i++)
    {
        printf("\n%d", p[i]);
    }

    char str[1024] = "hello  boygod";
    char *pstr = malloc(sizeof(char)*  (strlen(str) + 1));//分配内存,处理\0+1

    char *pnew=mynewmemcpy(pstr, str, strlen(str)+1);//拷贝\0
    printf("\n%s", pstr);
    printf("\n%s", pnew);//返回值是void*,拷贝成功的地址

    system("pause");
}
memset函数
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>


void *   mymemset(void * _Dst, int _Val, size_t _Size)
{
    if (_Dst ==NULL)
    {
        return NULL;
    }
    for (int i = 0; i < _Size;i++)
    {
         ( (char*)_Dst) [i] = _Val;//下标法
    }
    return _Dst;
}

void *   mymemsetaddr(void * _Dst, int _Val, size_t _Size)
{
    //((char*)_Dst) + _Size注意类型
    if (_Dst == NULL)
    {
        return NULL;
    }
    for (char *p = _Dst; p < ((char*)_Dst) + _Size;p++)
    {
        *p = _Val;//指针法
    }
    return _Dst;


}

void main()
{

    int a[5] = { 1, 2, 3, 4, 5 };
    double db[5] = { 1.1, 2.2, 3.3, 4.4, 5.5 };
    char str[1024] = "hello world";

    mymemsetaddr(a, 0, 20);
    mymemsetaddr(db, 0, 40);//整数,实数清零

    mymemsetaddr(str,'A', 1023); //填充
    //数据填充
    for (int i = 0; i < 5;i++)
    {
        printf("\n%d,%f", a[i], db[i]);
    }
    printf("%s", str);

    system("pause");

}
memmove(拷贝)实现
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


void *   mymemmove(void * _Dst, const void * _Src, size_t _Size)
{
    if (_Dst ==NULL  || _Src ==NULL)
    {
        return NULL;
    }


    void *psrc = malloc(_Size);//分配内存
    memcpy(psrc, _Src, _Size);//整体拷贝到临时内存
    memcpy(_Dst, psrc, _Size);//临时内存拷贝到
    free(psrc);//释放内存
    return _Dst;

}



void main()
{
    int a[5] = { 1, 2, 3, 4, 5 };
    int b[5] = {0};
    for (int i = 0; i < 5;i++)
    {
        printf("\n%d,%d", a[i], b[i]);
    }
    mymemmove(b, a, 12);

    for (int i = 0; i < 5; i++)
    {
        printf("\n%d,%d", a[i], b[i]);
    }

    char str1[32] = "abcdefghijklmnopq";
    char str2[32] = "*****************";

    mymemmove(str2, str1, 6);
    printf("\n%s,%s",str1, str2);
    mymemmove(str1+2, str1, 4);

    printf("\n%s,%s", str1, str2);
    system("pause");
} 
memccpy(拷贝,遇到设定值终止拷贝)实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


void *  my_memccpy( void * _Dst,  const void * _Src, int _Val,  size_t _MaxCount)
{
    char *dst = _Dst;
    char *src = _Src;//指针转换

    for (int i = 0; i < _MaxCount;i++)
    {
        if ((dst[i] = src[i]) == _Val)//下标法
        {
            break;
        }
    }
}

void *  my_memccpyaddr(void * _Dst, const void * _Src, int _Val, size_t _MaxCount)
{
    char *dst = _Dst;
    char *src = _Src;//指针转换
    int i = 0;
    while (i<_MaxCount)//控制循环次数
    {
        //*dst = *src;//指向的字符赋值
        //if (*dst ==_Val)
        //{
        //  break;
        //}
        //dst++;
        //src++;
        //i++;
        ;//指向的字符赋值
        if ((*dst++ = *src++) == _Val)
        {
            break;
        }
        i++;
    }
}




void main()
{
    char str[100] = "i am  wuwei,many girls love me ";

    char *pstr = (char[128]){0};//(char[128]){0}栈上

    my_memccpyaddr(pstr, str, 'g', 30);//往前拷贝30个字符,遇到字符'g'提前终止

    printf("%s", pstr);

    system("pause");
}

转载于:https://www.cnblogs.com/lhfen/p/6106400.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值