前段时间准备面试,看了一些库函数的实现,在看到memcpy时,发现有处理source和destination所指内存有重叠的情况,而strcpy没有,特别模仿库函数写了这个函数,并进行了测试.以下是具体的source code 和测试结果.
 
char *strcpy2(char *strDest, const char *strSrc)
{
assert( (strDest!=NULL) && ( strSrc!=NULL));
 if ( strDest == strSrc)
  return strDest ;
 char *tempptr = strDest ;
while( (*strDest++ = *strSrc++) != '\0')
;
return tempptr ;
}
这是修改网络上source code得到的一个版本,简洁,完全可以工作.初看觉得在程序内部改变了strDest和strSrc的地址(确实如此),不是太好,而实际上当别的函数调用后strDest和strSrc的地址恢复到调用前,因为调用只是改变参数的副本,程序改变地址指向的内容,而没有改变地址本身.不过更加明了的写法是用两个零时变量来替代,修改后如下:
char *strcpy3(char *strDest, const char *strSrc)
{
assert( (strDest!=NULL) && ( strSrc!=NULL));
 if ( strDest == strSrc)
   return strDest ;
 char *pDest = strDest ;
 char *pSrc=\'#\'" /> while( (*pDest ++ = *pSrc ++) != '\0');
 return strDest;
}
和strcpy2相比,增加了一个变量,不过程式更清晰,看个人爱好了.我偏向strcpy3.呵呵.
 
void memcpy2(void *pDst,const void *pSrc, size_t size)
{
 assert(pDst != NULL);
 assert(pSrc != NULL);
 //src and dst has a  shared area.
 if((pSrc<pDst) && ((char*)pSrc+size > pDst))
 {
  char *pstrSrc= (char *)pSrc + size -1;
  char *pstrDst = (char *)pDst + size -1;
while(size--)
   *pstrDst -- = *pstrSrc--;
 }
 else
 {
  char *pstrSrc= (char *)pSrc ;
  char *pstrDst = (char *)pDst ;
while(size--)
   *pstrDst++ = *pstrSrc++;
 }
}
 
 
int main()
{
 char *pSrc = (char *)malloc(1024);
 char *pDst = pSrc+4;
 strcpy2(pSrc,"12345678910");
 strcpy2(pDst,pSrc);    //(1)
 printf("Before memcpy: pSrc =%s pDst =%s\n",pSrc,pDst);
 memcpy2(pDst,pSrc,strlen(pSrc)*sizeof(char));
 printf("After memcpy: pSrc =%s \n pDst =%s\n",pSrc,pDst);
 return 0;
}
 
测试结果:
1.如果没有注释掉语句(1),执行到词语时,因为pDst覆盖了pSrc的结束符'\0'而陷入死循环,最后访问到不该访问的地址空间而出现debug错误.
2.注释掉语句(1),执行 memcpy2后,pSrc变成"123412345678910########",pDst变成"12345678910####","#"表示乱码,原因也是原有的结束符被覆盖.程序可以结束.
 
 
总结:
 1.const在特定的情况下并不能保证它所修饰函数参数为只读.
 2.在内存块有重叠的情况下,strcpy会崩溃,memcpy不会.

strcpy,memcpy,内存块重叠的更多相关文章

  1. 字符串函数(strcpy字符串拷,strcmp字符串比较,strstr字符串查找,strDelChar字符串删除字符,strrev字符串反序,memmove拷贝内存块,strlen字符串长度)

    1.strcpy字符串拷贝拷贝pStrSource到pStrDest,并返回pStrDest地址(源和目标位置重叠情况除外) char *strcpy(char *pStrDest, const ch ...

  2. C语言memmove()函数: 复制内存内容(可以重叠的内存块)

    头文件:#include <string.h> memmove() 用来复制内存内容,其原型为: void * memmove(void *dest, const void *src, s ...

  3. strcpy, memcpy, memset函数

    一. strcpy函数 原型声明:char *strcpy(char* dest, const char *src);   头文件:#include <string.h> 和 #inclu ...

  4. C++实现简单的内存块自己主动管理

    #ifndef __MEM__H #define __MEM__H #include<iostream> using namespace std; //自己主动管理内存块 typedef ...

  5. strcpy函数内存分析

    void strcpy(char* strDest, char* strSrc) { while((*strDest++ = *strSrc++) != '\0'); } 看上面这段代码,只有一条语句 ...

  6. Python解析器源码加密系列之(二):一次使用标准c的FILE*访问内存块的尝试

    摘要:由于近期打算修改Python解释器以实现pyc文件的加密/解密,出于保密的要求,解密之后的数据只能放在内存中,不能写入到文件中.但是后续的解析pyc文件的代码又只能接受FILE*作为入参,所以就 ...

  7. memcpy内存拷贝及优化策略图解

    一般内存拷贝与优化 代码实现 #include<iostream> usingnamespace std; //不安全的内存拷贝(当源内存地址与目标内存地址重叠时会产生错误) void h ...

  8. 固定尺寸内存块的缓冲队列类及C++实现源代码

    -------------------------------------------------------------------------------- 标题: 固定尺寸内存块的缓冲队列类及实 ...

  9. access_ok | 检查用户空间内存块是否可用

    access_ok() 函数是用来代替老版本的 verify_area() 函数的.它的作用也是检查用户空间指针是否可用. 函数原型:access_ok (type, addr, size); 变量说 ...

随机推荐

  1. 尝试设计LFSR加密器,并用CAP4验证随机性

    在CPA4软件中有提供设计LFSR加密器的功能: 输入LFSR的大小,初始密钥,还有反馈密钥. 点击Set Key后点击Show LFSR 观察LFSR,发现初始密钥是1101,转成十六进制是D,反馈 ...

  2. Makefile隐含规则和用到的默认变量

    如果要使用隐含规则生成你需要的目标,你所需要做的就是不要写出这个目标的规则.那么,make会试图去自动推导产生这个目标的规则和命令,如果make可以自动推导生成这个目标的规则和命令,那么这个行为就是隐 ...

  3. 《APUE》第三章笔记(2)

    read函数 调用read函数从打开的文件中读数据. #include <unistd.h> ssize_t read(int filedes, void *buf, size_t nby ...

  4. 移动端REM布局方案

    引用http://www.w3cplus.com/mobile/lib-flexible-for-html5-layout.html的方案 下载地址https://github.com/hupan50 ...

  5. FusionCharts xml入门教程

    由于项目需求需要做一个报表,选择FusionCharts作为工具使用.由于以 前没有接触过报表,网上也没有比较详细的fusionCharts教程,所以决定好好研究FusionCharts,同时做一个比 ...

  6. pyes-elasticsearch的python客户端使用笔记

    elasticsearch入门:  http://www.qwolf.com/?p=1387 一.重要的概念 http://834945712.iteye.com/blog/1915432 这篇文章很 ...

  7. C# 中经常用到的HTTP请求类,已封装get,post,delete,put

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.N ...

  8. 类集对enum的支持。

    1,EmumMap public class EnumMap<K extends Enum<K>,V>extends AbstractMap<K,V>impleme ...

  9. MySQL中的max_connections和max_user_connections 及 MySQL服务器最大连接数的合理设置

    max_connections 是指整个mysql服务器的最大连接数: max_user_connections 是指每个数据库用户的最大连接数,比如:虚拟主机可以用这个参数控制每个虚拟主机用户的数据 ...

  10. Kaggle Competition Past Solutions

    Kaggle Competition Past Solutions We learn more from code, and from great code. Not necessarily alwa ...