C/C++之Memcpy and memmove
memcpy与memmove的目的都是将N个字节的源内存地址的内容拷贝到目标内存地址中。
但当源内存和目标内存存在重叠时,memcpy会出现错误,而memmove能正确地实施拷贝,但这也增加了一点点开销。
memmove的处理措施:
(1)当源内存的首地址等于目标内存的首地址时,不进行任何拷贝
(2)当源内存的首地址大于目标内存的首地址时,实行正向拷贝
(3)当源内存的首地址小于目标内存的首地址时,实行反向拷贝
-- memcpy实现
| 1 | void* memcpy(void* dest, constvoid* src, size_tn) | 
| 2 | { | 
| 3 | char* d = (char*) dest; | 
| 4 | constchar* s = (constchar*) src; | 
| 5 | while(n-–) | 
| 6 | *d++ = *s++; | 
| 7 | returndest; | 
| 8 | } | 
Notes:
- memcpy的参数指针类型是void*,具体赋值操作是以字节为单位。
- 必须进行类型转换。
- 返回的还是void*型的dest。
-- memmove实现
| 01 | void* memmove(void* dest, constvoid* src, size_tn) | 
| 02 | { | 
| 03 | char* d = (char*) dest; | 
| 04 | constchar* s = (constchar*) src; | 
| 05 | 
| 06 | if(s>d) | 
| 07 | { | 
| 08 | // start at beginning of s | 
| 09 | while(n--) | 
| 10 | *d++ = *s++; | 
| 11 | } | 
| 12 | elseif(s<d) | 
| 13 | { | 
| 14 | // start at end of s | 
| 15 | d = d+n-1; | 
| 16 | s = s+n-1; | 
| 17 | 
| 18 | while(n--) | 
| 19 | *d-- = *s--; | 
| 20 | } | 
| 21 | returndest; | 
| 22 | } | 
示意图:
(1)内存低端 <-----s-----> <-----d-----> 内存高端 start at end of s
(2)内存低端 <-----s--<==>--d----->      内存高端 start at end of s
(3)内存低端 <-----sd----->              内存高端 do nothing
(4)内存低端 <-----d--<==>--s----->      内存高端 start at beginning of s
(5)内存低端 <-----d-----> <-----s-----> 内存高端 start at beginning of s
Notes:
- s==d时,什么都不做。
- d在前,正向拷贝。
- d在后,逆向拷贝。
1.memmove 函数原型:void *memmove(void *dest, const void *source, size_t count) 返回值说明:返回指向dest的void *指针 参数说明:dest,source分别为目标串和源串的首地址。count为要移动的字符的个数 函数说明:memmove用于从source拷贝count个字符到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中。 2.memcpy 函数原型:void *memcpy(void *dest, const void *source, size_t count); 返回值说明:返回指向dest的void *指针 函数说明:memcpy功能和memmove相同,但是memcpy中dest和source中的区域不能重叠,否则会出现未知结果。
原型:extern char *strcpy(char *dest,char *src); 功能:把src所指由NULL结束的字符串复制到dest所指的数组中。 说明:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串,返回指向dest的指针。
其实在strcpy的实现比较多,但思想是一致的,一般用C来实现,但是memcpy和memmove这样的函数可能是用汇编实现的,并且充分利用块拷贝的思想,不会单字节单字节的拷贝。所以效率strcpy<memcpy.
memmove一般由于要判断内存是否重合,效率也会较memcpy低些。
1 /***
2 * @brief 以字节的方式直接拷贝
3 * 库中实现是以汇编实现,
4 * 其实可以直接调用strncat函数
5 * **/
6 void *memcpy(void *dst,void *src,size_t n)
7 {
8 char *dp = (char *)dst;
9 char *sp = (char *)src;
10 assert((src!=0)&&(dst!=0)&&(n>0));//not null
11 while(n--)
12 *(dp++) = *(sp++);
13 /**!边界*/
14 dp = '\0';
15 return dst;
16 }
 memmove
memmove
1 void *memmove(void *dst,const void *src,int n)
2 {
3 char *dp = (char *)dst;
4 char *sp = (char *)src;
5 assert((src!=0)&&(dst!=0)&&(n>0));//not null
6 //非重叠
7 //dp < sp
8 //dp > (sp+n)
9 if(dp<sp||(sp+n)>=dp)
10 {
11 while(n--)
12 *(dp++) = *(sp++);
13 *dp = '\0';
14 }else if(sp<dp)//重叠 (此时条件 sp<dp<(sp+n))如果sp==dp则快速的返回
15 {//反向拷贝
16 sp += n;
17 dp += n;
18 *dp = '\0';
19 while(n--)
20 *(--dp) = *(--sp);
21 }
22 return dst;
23 }
注意对于重合的要反向拷贝
/*
 *Magicman
 *myMemcpy.c
 *不调用库函数,实现内存拷贝
*/
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
void *myMemcpy(void *dest, const void *src, int len)
{
    assert((dest != NULL) && (src != NULL) && (len >= 0));
    if (dest == src)
    {
        return dest;
    }
    while (len-- > 0)
    {
        *(char *)dest++ = *(char *)src++;
    }
    return dest;
}
int main(int argc, char argv[])
{
    char str[20] = "Testing myMemory!";
    char pstr[20] = "";
    char *pp = str;
    int ia[10] = {1,2,3,4,5,6,7,8,9,10};
    int ib[10] = {};
    int *ip = NULL;
myMemcpy((void *)pstr, (void *)str, sizeof(str));
printf("%s/n", pstr);
printf("%s/n", myMemcpy((void *)pp, (void *)str, 20));
myMemcpy((void *)ib, (void *)ia, 5*sizeof(int));
for (ip = ib; ip < ib + 10; ip++)
    {
        printf("%d  ", *ip);
    }
printf("/n");
    
    return 0;
}
让自己实现memcpy库函数,要求考虑特殊情况,两段内存存在覆盖,以及指针为空的情况。
几点结论: 
1,memcpy实现从源source中拷贝n个字节到目标destin中,src源数据应该保留。
2,memmove实现移动一块字节,src源数据可以不保留。
3,memcpy没有考虑内存覆盖问题(由assert条件可知);而memmove考虑了内存覆盖问题,并给出了解决办法。
4,memcpy和memmove中不需要考虑数组越界问题,dst的长度应该大于src的长度,这是调用者应该考虑的问题。
C/C++之Memcpy and memmove的更多相关文章
- memcpy vs memmove
		[本文连接] http://www.cnblogs.com/hellogiser/p/memcpy_vs_memmove.html [分析] memcpy与memmove的目的都是将N个字节的源内存地 ... 
- memcpy与memmove的区别
		在面试中经常会被问道memcpy与memove有什么区别? 整理如下: 其实主要在考C的关键字:restrict C库中有两个函数可以从一个位置把字节复制到另一个位置.在C99标准下,它们的原型如下: ... 
- C语言实现memcpy和memmove
		0.两者比较: memmove用于从src拷贝count个字符到dest,如果目标区域和源区域有重叠的话,memmove能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中.但复制后src内容会被 ... 
- memcpy、memmove、memset及strcpy函数实现和理解
		memcpy.memmove.memset及strcpy函数实现和理解 关于memcpy memcpy是C和C++ 中的内存拷贝函数,在C中所需的头文件是#include<string.h> ... 
- 关于memcpy和memmove的一点说明
		今天看到书上降到memcpy和memmove的区别才突然发现原来两者之间有如此区别,以前只知道这两个函数是 实现同样的功能,没有接触到其不同. memcpy和memmove在MSDN的定义如下: 从两 ... 
- strcpy()、memcpy()、memmove()、memset()的内部实现
		一直想知道 strcpy().memcpy().memmove().memset()的内部实现 strcpy(), 字符串拷贝. char *strcpy(char *strDest, const c ... 
- 第 16 章 C 预处理器和 C 库(string.h 库中的 memcpy() 和 memmove())
		/*----------------------------------------- mems.c -- 使用 memcpy() 和 memmove() ---------------------- ... 
- 模拟实现memcpy 与 memmove
		模拟实现memcpy 与 memmove 1.str系列的函数只能处理字符串——>必须带有'\0'2.memcpy内存处理函数:不涉及'\0',需要包含头文件 string.h3.source的 ... 
- memcpy、memmove、memset、memchr、memcmp、strstr详解
		第一部分 综述 memcpy.memmove.memset.memchr.memcmp都是C语言中的库函数,在头文件string.h中.memcpy和memmove的作用是拷贝一定长度的内存的内容,m ... 
随机推荐
- Shell转义字符与变量替换
			转义字符 含义 \\ 反斜杠 \a 警报,响铃 \b 退格(删除键) \f 换页(FF),将当前位置移到下页开头 \n 换行 \r 回车 \t 水平制表符(tab键) \v 垂直制表符 vim te ... 
- 生存分析(survival analysis)
			一.生存分析(survival analysis)的定义 生存分析:对一个或多个非负随机变量进行统计推断,研究生存现象和响应时间数据及其统计规律的一门学科. 生存分析:既考虑结果又考虑生存时间的一种统 ... 
- 无向连通图求割边(桥)hdu4738,hdu3849
			点击打开链接 题目链接: hdu 4738 题目大意: 曹操有N个岛,这些岛用M座桥连接起来 每座桥有士兵把守(也可能没有) 周瑜想让这N个岛不连通,但只能炸掉一座桥 并且炸掉一座桥需要派出不 ... 
- Kibana在Linux上安装部署及使用说明
			Kibana安装及使用说明 Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索.查看交互存储在Elasticsearch索引中的数据. 官方地址:https://www. ... 
- php中调用这个功能可以在web页面中显示hello world这个经典单词
			php程序写的时间长了,自然对他所提供的功能了如指掌,他所提供的一大堆功能,真是觉得很好用,但有时候会发现php也缺少一些功能,自己总是会产生为php添加一些自定义的功能的想法.久而久之,终于今天憋不 ... 
- 2018牛客网暑期ACM多校训练营(第三场) A - PACM Team - [四维01背包][四约束01背包]
			题目链接:https://www.nowcoder.com/acm/contest/141/A 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K ... 
- Oracle安装部署之 oracle 11g install linux
			#!/bin/bash#Purpose:Create and config oracle install.#Usage:Log on as the superuser('root') #1.creat ... 
- pro 图层 叹号
			同事遇到问题,后来他自己探索解决了~~大致记录如下 pro1.4中打开mxd,部分图层前显示叹号.根据arcmap的经验,点击叹号去修复,结果显示 不支持类型数据. 后解决办法:新建pro 的proj ... 
- maven国内稳定的阿里源
			<mirror> <id>nexus-aliyun</id> <mirrorOf>*</mirrorOf> <name>Nexu ... 
- Linux输入输出重定向和文件查找值grep命令
			Linux输入输出重定向和文件查找值grep命令 一.文件描述符Linux 的shell命令,可以通过文件描述符来引用一些文件,通常使用到的文件描述符为0,1,2.Linux系统实际上有12个文件描述 ... 
