前段时间准备面试,看了一些库函数的实现,在看到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. 九度OJ 1433 FatMouse -- 贪心算法

    题目地址:http://ac.jobdu.com/problem.php?pid=1433 题目描述: FatMouse prepared M pounds of cat food, ready to ...

  2. Spring-Boot-XML-Restful-Service

    http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-write-an-xml-rest-service ...

  3. mysql扩展库操作mysql数据库

    环境搭建 启用mysql扩展库,在php.ini文件中去配置mysql扩展库 extension=php_mysql.dll 查询数据库 1.建库建表 //建库testcreate database ...

  4. 针对IE的CSS hack 全面 实用

    .all IE{property:value\9;} .gte IE 8{property:value\0;} .lte IE 7{*property:value;} .IE 8/9{property ...

  5. #Leet Code# Populating Next Right Pointers in Each Node II

    描述:注意需要先self.connect(right)再self.connect(left),否则会有case通不过,原因是左边递归执行时依赖与右边的next已经建立,而先执行connect(left ...

  6. extjs中第一次访问有效,第二次访问出现部分组件无法显示的,动态改变组件的label值的方法,ExtJs中组件最好少使用ID属性(推荐更多使用Name属性)

    在公司做的一个OA项目中,曾经就遇到了这样的一个问题:(我是在jsp中的div中将js render到div中去的)第一次访问此界面的时候,formpanel上的组件能正常显示,不刷新整个页面的前提下 ...

  7. No Hibernate Session bound to thread, and configuration does not allow creat

    No Hibernate Session bound to thread, and configuration does not allow creat 今天遇到这么一个错误,在网上差了很多都没有能解 ...

  8. 存储过程&Function

    存储过程&Function 编号 类别 ORACLE MYSQL 注释 1 创建存储过程语句不同 create or replace procedure P_ADD_FAC(   id_fac ...

  9. 防御XSS攻击的七条原则

    本文将会着重介绍防御XSS攻击的一些原则,需要读者对于XSS有所了解,至少知道XSS漏洞的基本原理,如果您对此不是特别清楚,请参考这两篇文章:<Stored and Reflected XSS ...

  10. 【HDU 3435】 A new Graph Game (KM|费用流)

    A new Graph Game Problem Description An undirected graph is a graph in which the nodes are connected ...