当前位置: 首页 > news >正文

内存操作函数memcpy和memmove详解

内存操作函数memcpy和memmove详解

  在C/C++中,根据定义,字符串由一个'\0'字节结尾,所以字符串内部不能包含'\0'字符。但是,非字符串数据内部包含'\0'的情况并不少见。你无法使用字符串函数(strcpy,strcat,strcmp等等字符串处理函数)来处理这种类型的数据,因为它们遇到第一个'\0'之后就停止工作。

  因此C/C++中提供了另外一组mem***函数来处理内存操作,它们可以处理包括'\0'在内的任意字节,这些函数都接受一个长度参数。memcpy从源参数向目标参数复制由长度参数指定的字节数。memmove函数执行相同的功能,但它功能更加强大,能够正确处理源参数和目标参数出现内存重叠的情况。但通常由于memmove无法使用某些机器提供的特殊字节-字符串处理指令,所以它可能比memcpy慢一些。

  源参数和目标参数在内存中分布情况分为重叠和不重叠,而重叠又分为源参数在目标参数的前面和源参数在目标参数的后面。memcopy只能处理不重叠和源参数在目标参数的后面的情况,而memmove能处理所有的情况。具体可以参考如下代码:

  

void *memcpy (void *dst, void *src, size_t length)
{
    if (NULL == dst || NULL == src)
        return NULL;
    char *temp_dst = (char*)dst;
    char *temp_src = (char*)src;
    for (size_t len = 0; len < length; ++len) //从前往后复制
    {
        *temp_dst++ = *temp_src++;
    }
    return dst;
}

void *memmove (void *dst, void *src, size_t length)
{
    if (NULL == dst || NULL == src)
        return NULL;
    char *temp_dst = (char*)dst;
    char *temp_src = (char*)src;
    if (temp_src < temp_dst) //从后往前复制
    {
        temp_dst += length - 1;
        temp_src += length - 1;
        for (size_t len = 0; len < length; ++len)
        {
            *temp_dst-- = *temp_src--;
        }
    }
    else //从前往后复制
    {
        for (size_t len = 0; len < length; ++len)
        {
            *temp_dst++ = *temp_src++;
        }
    }

    return dst;
}

 

完整的实现及测试如下:

#include <iostream>
using namespace std;

void *memcpy (void *dst, void *src, size_t length);
void *memmove (void *dst, void *src, size_t length);


void *memcpy (void *dst, void *src, size_t length)
{
    if (NULL == dst || NULL == src)
        return NULL;
    char *temp_dst = (char*)dst;
    char *temp_src = (char*)src;
    for (size_t len = 0; len < length; ++len) //从前往后复制
    {
        *temp_dst++ = *temp_src++;
    }
    return dst;
}

void *memmove (void *dst, void *src, size_t length)
{
    if (NULL == dst || NULL == src)
        return NULL;
    char *temp_dst = (char*)dst;
    char *temp_src = (char*)src;
    if (temp_src < temp_dst) //从后往前复制
    {
        temp_dst += length - 1;
        temp_src += length - 1;
        for (size_t len = 0; len < length; ++len)
        {
            *temp_dst-- = *temp_src--;
        }
    }
    else //从前往后复制
    {
        for (size_t len = 0; len < length; ++len)
        {
            *temp_dst++ = *temp_src++;
        }
    }

    return dst;
}

int main ()
{
    char a[20] = "Hello joel";
    char b[20];
    char *p = NULL;
    p = (char*)memcpy (b, a, 10);
    while ('\0' != *p)
    {
        cout << *p;
        p++;
    }
    cout << "\n";
    p = (char*)memmove (a + 1, a, 10);
    while ('\0' != *p)
    {
        cout << *p;
        p++;
    }
    return 0;
}

 

输出结果为:

Hello joel
Hello joel

转载于:https://www.cnblogs.com/uestcjoel/p/6672663.html

相关文章:

  • 【原】STM32的USART与SPI是可以直接通讯
  • django自定义signal的发送和接收样例
  • MVC开发中的常见错误-07-“System.IO.DirectoryNotFoundException”类型的未经处理的异常在 mscorlib.dll 中发生...
  • 你必须要了解的几种排序方法
  • 补交 作业二:个人博客作业内容:需求分析
  • poj-1741 (点分治模板)
  • 分库分表中间件特性分析
  • 百科知识 scm文件如何打开
  • PHP之旅3 php数组以及遍历数组 以及each() list() foreach()
  • Spring配置activemq异步消息监听器
  • HTML起步——学习2
  • 1.Zabbix 3.0 基础
  • bzoj4823[CQOI2017]老C的方块
  • 工资计算(用SQL来计算)
  • 电梯演说模板练习
  • python3.6+scrapy+mysql 爬虫实战
  • git 常用命令
  • hadoop集群管理系统搭建规划说明
  • Java 实战开发之spring、logback配置及chrome开发神器(六)
  • react 代码优化(一) ——事件处理
  • Ruby 2.x 源代码分析:扩展 概述
  • 分布式事物理论与实践
  • 回顾 Swift 多平台移植进度 #2
  • 前嗅ForeSpider采集配置界面介绍
  • 责任链模式的两种实现
  • 7行Python代码的人脸识别
  • 阿里云API、SDK和CLI应用实践方案
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • # Maven错误Error executing Maven
  • #pragam once 和 #ifndef 预编译头
  • #设计模式#4.6 Flyweight(享元) 对象结构型模式
  • (+4)2.2UML建模图
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (剑指Offer)面试题41:和为s的连续正数序列
  • (小白学Java)Java简介和基本配置
  • (转)C语言家族扩展收藏 (转)C语言家族扩展
  • (转)linux自定义开机启动服务和chkconfig使用方法
  • (转)大型网站的系统架构
  • **CI中自动类加载的用法总结
  • .NET 使用配置文件
  • .net6解除文件上传限制。Multipart body length limit 16384 exceeded
  • @Autowired多个相同类型bean装配问题
  • [100天算法】-目标和(day 79)
  • [2010-8-30]
  • [BT]BUUCTF刷题第9天(3.27)
  • [bzoj1324]Exca王者之剑_最小割
  • [E链表] lc83. 删除排序链表中的重复元素(单链表+模拟)
  • [Jquery] 实现鼠标移到某个对象,在旁边显示层。
  • [Python]—Linux Server 系统监控程序
  • [Python人工智能] 四十四.命名实体识别 (5)利用bert4keras构建Bert-CRF实体识别模型(实体位置)
  • [Real world Haskell] 中文翻译:前言
  • [Rust学习:二]变量和传参
  • [sqoop] sqoop 小试牛刀
  • [svc]logstash和filebeat之间ssl加密