探讨strcpy函数的实现(下)

        昨天探讨了关于strcpy函数的一般实现方式:

[cpp]  view plain copy
  1. </pre><pre name="code" class="cpp">char* Mystrcpy(char* dst, const char* src)  
  2. {  
  3.     assert(dst != NULL && src != NULL);  
  4.     char* ret = dst;  
  5.     while((*dst++ = *src++) != '\0');  
  6.     return ret;  
  7. }  
         这种实现方式应该是我们在笔试中比较好想到并且能够写出的

以下内容依旧转自:博客园-Norcy

但是上述代码并没有考虑到dst和src内存重叠的情况,即

[cpp]  view plain copy
  1. char s[10] = "hello";  
  2. Mystrcpy(s, s+1);//应返回ello  
  3. //Mystrcpy(s+1, s);//应返回hhello,但实际会报错,因为dst与src重叠了,把'\0'覆盖了  
所谓重叠,就是src未处理的部分已经被dst覆盖了,只有一种情况:src <= dst <= src + strlen(src)

C函数memcpy自带内存重叠检测功能,下面给出memcpy的的实现Mymemcpy

[cpp]  view plain copy
  1. char* Mymemcpy(char* dst, const char* src, int cnt)  
  2. {  
  3.     assert(dst != NULL && src != NULL);  
  4.     char* ret = dst;  
  5.     if(dst >= src && dst <= src + cnt -1)//内存重叠,从高地址开始复制  
  6.    {  
  7.         dst = dst + cnt -1;  
  8.         src = src + cnt -1;  
  9.         while(cnt--)  
  10.             *dst-- = *src--;  
  11.     }  
  12.     else // 正常情况,从低地址开始复制  
  13.     {  
  14.         while(cnt--)  
  15.             *dst++ = *src++;  
  16.     }  
  17.     return ret;  
  18. }  
然后通过调用Mymemcpy函数实现考虑内存重叠情况下的Mystrcpy:

[cpp]  view plain copy
  1. char* Mystrcpy(char* dst, const char* src)  
  2. {  
  3.     assert(dst != NULL && src != NULL);  
  4.     char* ret = dst;  
  5.     Mymemcpy(dst, src, strlen(src) + 1);  
  6.     return ret;  
捋一捋代码逻辑吧……

Mymemcpy函数传递了三个参数,目的字符串地址,源字符串地址,要复制的字节个数(字符串长度加一)

当进入到函数体内部时,首先还是要判断指针有效性,保存原来的目的字符串地址

接下来判断内存是否重叠,当目的字符串的地址在源字符串第一个元素和最后一个元素的地址之间时,处于内存发生重叠的状态下,这个时候如果还按照从前向后的顺序复制,则从逻辑上源字符串被复制过来的内容覆盖,从而导致了源字符串的内容被改变(并不是通过指针来修改源字符串所以编译能够通过),但运行时程序会出错(具体错误原因不晓得,以后再深入研究),这个时候我们就应该换一个思路——从后向前复制(这种思路让我自己想我估计也是很费劲才能想出来,o(︶︿︶)o 唉,有一种代码,叫做别人的代码……)

让src指向源字符串的最后一个元素,dst也指向其加上源字符串长度之后的位置,然后向前复制cnt个字节

当然如果不是内存重叠的情况下就还是直接从前向后复制就好了(我在想Mymemcpy函数就不用判断内存是否重叠直接从后向前复制是不是代码能够简洁点呢……当然学习的话还是判断一下好,还没想出不判断是否重叠直接采用从后向前的方式复制有什么不好的地方……)

而且笔试面试的时候往往题目中还要求不能够使用库函数,如果有这个要求的话应该不用考虑内存重叠的情况了吧,毕竟调用Mymencpy的时候调用了strlen这个函数

一般情况下用一般方式的实现就应该可以了

【本文转至】http://blog.csdn.net/a3789910/article/details/41450373



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值