3315|12

7815

帖子

56

TA的资源

裸片初长成(中级)

楼主
 

strcpy实现之 辛昕版 [复制链接]

 
本帖最后由 辛昕 于 2018-6-6 11:48 编辑

这件事告诉我们,没有测试就随手写,还以为木有问题,是一定会被打脸的。
而且现世报来的特别快。
这种态度是不对的,一定要改。

骚瑞骚瑞,把这事忘了,我果然是没啥责任心啊,诶~~
好吧,先上代码
  1. char *xx_strcpy(char *s1,char *s2)
  2. {
  3.        char *temp;
  4.        uint32_t s2_len = 0,i;
  5.       
  6.        if( (s1 == NULL) || (s2 == NULL) )
  7.             return NULL;
  8.   
  9.        temp = s2;
  10.       
  11.        while(*temp != 0)
  12.        {
  13.              temp++;
  14.              s2_len++;
  15.        }

  16.        for(i = s2_len;i > 0;i-- )
  17.              *(s1+i) = *(s2+i);

  18.        return s1;
  19. }
复制代码



此帖出自编程基础论坛

最新回复

这种情况下从头开始确实是会出现被填0的情况,但是这种用法本身有潜在的危险,会对原字符串进行破坏,还有可能会出现溢出错误,如果原字符串是字符串常量,你这样就会出问题。如果是相当有把握,保证原字符串之后的内存空间可以使用,不溢出,也是可以用。  详情 回复 发表于 2018-6-6 15:58
点赞 关注
个人签名

强者为尊,弱者,死无葬身之地

 

回复
举报

3416

帖子

0

TA的资源

纯净的硅(高级)

沙发
 
看完楼主造的轮子,不由得感叹一句,面向对象真TM好用……
此帖出自编程基础论坛
 
 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

板凳
 
ljj3166 发表于 2018-6-6 10:46
看完楼主造的轮子,不由得感叹一句,面向对象真TM好用……

你说的是C++ string吧
此帖出自编程基础论坛
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

4
 
恕我蠢,不理解什么叫 一个方向的重叠@lcofjp
        // 没啥毛病,至于那个  少copy了一个字节 和 加0的毛病,认。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <string.h>

  5. char *xx_strcpy(char *s1,char *s2)
  6. {
  7.        char *temp;
  8.        uint32_t s2_len = 0;
  9.            int i;
  10.       
  11.        if( (s1 == NULL) || (s2 == NULL) )
  12.             return NULL;
  13.   
  14.        temp = s2;
  15.       
  16.        while(*temp != 0)
  17.        {
  18.              temp++;
  19.              s2_len++;
  20.        }

  21.        for(i = s2_len;i >= 0;i-- )
  22.              *(s1+i) = *(s2+i);
  23.                
  24.            *(s1 + s2_len + 1) = 0;

  25.        return s1;
  26. }



  27. #define TEST_STRING "IDOYOULOVE"

  28. int main(void)
  29. {
  30.         char s[12];
  31.        
  32.        
  33.         strcpy(s,TEST_STRING);
  34.        
  35.         printf("strcpy:%s\n",s);
  36.        
  37.         xx_strcpy(s,(char *)(TEST_STRING + 4));
  38.        
  39.         printf("XX:%s\n",s);

  40.         // 我也试过反过来,,先 strcpy(TEST_STRING + 4) 再 xx_strcpy(TEST_STRING)的;
  41.         // 没啥毛病,至于那个  少copy了一个字节 和 加0的毛病,认。
  42.        
  43. }
复制代码

此帖出自编程基础论坛
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

5
 
https://c.runoob.com/compile/12
公司电脑加密了,太多毛病,我直接在线跑的。
此帖出自编程基础论坛
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复

1976

帖子

0

TA的资源

五彩晶圆(初级)

6
 
while循环后面的for循环有些多余,我之前回帖写的除了没有判断参数的合法性和返回值不一样,基本思路跟版主的差不多
此帖出自编程基础论坛
 
 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

7
 
按照 lcoftp 说的,试试非字面量,而是一个 可读可写的 字符串数组
依然没啥发现
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <string.h>

  5. char *xx_strcpy(char *s1,char *s2)
  6. {
  7.        char *temp;
  8.        uint32_t s2_len = 0;
  9.            int i;
  10.       
  11.        if( (s1 == NULL) || (s2 == NULL) )
  12.             return NULL;
  13.   
  14.        temp = s2;
  15.       
  16.        while(*temp != 0)
  17.        {
  18.              temp++;
  19.              s2_len++;
  20.        }

  21.        for(i = s2_len;i >= 0;i-- )
  22.              *(s1+i) = *(s2+i);
  23.                
  24.            *(s1 + s2_len + 1) = 0;

  25.        return s1;
  26. }



  27. #define TEST_STRING "IDOYOULOVE"

  28. int main(void)
  29. {
  30.         char s[12];
  31.                 char src[12] = {'0','1','2','3','4','5','6','7','8','9','a'};
  32.         // 但这种写法要注意一个问题,比如一个12元素的数组,你要留最后一个位置,它会自动
  33.                 // 填充0,这是不初始化的默认值,假设没这个0,这个src事实上也不是一个字符串
  34.                 // 因为没有0结尾,所以会出现错误。
  35.                 // 这是我在写这个测试代码的过程中发现的。
  36.         
  37.         strcpy(s,src + 4);
  38.         
  39.         printf("strcpy:%s\n",s);
  40.         
  41.         xx_strcpy(s,src);
  42.         
  43.         printf("XX:%s\n",s);

  44.                 // 还是没啥毛病
  45.         
  46. }
复制代码
此帖出自编程基础论坛
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

8
 
bobde163 发表于 2018-6-6 11:18
while循环后面的for循环有些多余,我之前回帖写的除了没有判断参数的合法性和返回值不一样,基本思路跟版主 ...

虾米,你的回复?
不不不,我好像没看到有考虑到地址重叠,然后反过来复制的人。

我反过来复制不是编码习惯,是真的要反过来复制才能防止地址重叠,把0给冲没了。
此帖出自编程基础论坛
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复

1903

帖子

0

TA的资源

版主

9
 
大牛啊,学习了
此帖出自编程基础论坛
 
 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

10
 
@lcoftp 收到,被打脸了,等等哈
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <string.h>

  5. char *xx_strcpy(char *s1,char *s2)
  6. {
  7.        char *temp;
  8.        uint32_t s2_len = 0;
  9.            int i;
  10.       
  11.        if( (s1 == NULL) || (s2 == NULL) )
  12.             return NULL;
  13.   
  14.        temp = s2;
  15.       
  16.        while(*temp != 0)
  17.        {
  18.              temp++;
  19.              s2_len++;
  20.        }

  21.        for(i = s2_len;i >= 0;i-- )
  22.              *(s1+i) = *(s2+i);
  23.                
  24.            *(s1 + s2_len + 1) = 0;

  25.        return s1;
  26. }



  27. int main()
  28. {
  29.         char test1[20] = "hello world!\n";
  30.         char test2[20] = "hello world!\n";

  31.         printf(" --- 1 -----\n");
  32.         puts(xx_strcpy(test1, test1 + 2));
  33.         puts(xx_strcpy(test2 + 2, test2));

  34.         char test3[20] = "hello world!\n";
  35.         char test4[20] = "hello world!\n";

  36.         printf(" --- 2 ----\n");
  37.         puts((char*)memmove(test3, test3 + 2, 10));
  38.         puts((char*)memmove(test4 + 2, test4, 10));
  39.     return 0;
  40. }
复制代码

  1. // 运行结果
  2. --- 1 -----


  3. hello world!

  4. --- 2 ----
  5. llo world!d!

  6. hello worl
复制代码
此帖出自编程基础论坛
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复

1976

帖子

0

TA的资源

五彩晶圆(初级)

11
 
辛昕 发表于 2018-6-6 11:37
虾米,你的回复?
不不不,我好像没看到有考虑到地址重叠,然后反过来复制的人。

我反过来复制不是编 ...

防止地址重叠,这是什么原理?
此帖出自编程基础论坛
 
 
 

回复

7815

帖子

56

TA的资源

裸片初长成(中级)

12
 
本帖最后由 辛昕 于 2018-6-6 14:23 编辑
bobde163 发表于 2018-6-6 13:50
防止地址重叠,这是什么原理?

你只要画个图就明白了。
比方说
有一个数组
char s[20]; 它里面存的内容是 “0123456789012345” s[16] = 0;
好了,现在你要执行以下操作
strcpy(s + 12,s);
当你在copy的时候,s[16]早早就被填成了非0;
所以你永远找不到s结束的地方。

反过来复制,相当于我从一开始,就记录了本来结束的地方。
此帖出自编程基础论坛
 
个人签名

强者为尊,弱者,死无葬身之地

 
 

回复

1976

帖子

0

TA的资源

五彩晶圆(初级)

13
 
辛昕 发表于 2018-6-6 14:22
你只要画个图就明白了。
比方说
有一个数组
char s[20]; 它里面存的内容是 “0123456789012345” s[16 ...

这种情况下从头开始确实是会出现被填0的情况,但是这种用法本身有潜在的危险,会对原字符串进行破坏,还有可能会出现溢出错误,如果原字符串是字符串常量,你这样就会出问题。如果是相当有把握,保证原字符串之后的内存空间可以使用,不溢出,也是可以用。
此帖出自编程基础论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表