已知strcpy函数的原型是:

char *strcpy(char *dst, const char *src);

实现strcpy函数

解释为什么要返回char *

假如考虑dst和src内存重叠的情况,strcpy该怎么实现

1.strcpy的实现代码

char * strcpy(char *dst,const char *src) //[1]

{

assert(dst!= NULL && src != NULL); //[2]

char *ret = dst; //[3]

while ((*dst++=*src++)!='\0'); //[4]

returnret;

}

[1]const修饰

源字符串参数用const修饰,防止修改源字符串。

[2]空指针检查

(A)不检查指针的有效性,说明答题者不注重代码的健壮性。

(B)检查指针的有效性时使用assert(!dst && !src);

char *转换为bool即是类型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。

(C)检查指针的有效性时使用assert(dst != 0 && src != 0);

直接使用常量(如本例中的0)会减少程序的可维护性。而使用NULL代替0,如果出现拼写错误,编译器就会检查出来。

[3]返回目标地址

(A)忘记保存原始的strdst值。

[4]'\0'

(A)循环写成while (*dst++=*src++);明显是错误的。

(B)循环写成while (*src!='\0') *dst++=*src++;

循环体结束后,dst字符串的末尾没有正确地加上'\0'。

2.为什么要返回char *?

返回dst的原始值使函数能够支持链式表达式。

链式表达式的形式如:

int l=strlen(strcpy(strA,strB));

又如:

char * strA=strcpy(new char[10],strB);

返回strSrc的原始值是错误的。

其一,源字符串肯定是已知的,返回它没有意义。

其二,不能支持形如第二例的表达式。

其三,把const char *作为char *返回,类型不符,编译报错。

3.假如考虑dst和src内存重叠的情况,strcpy该怎么实现

char s[10]="hello";

strcpy(s, s+1); //应返回ello,

//strcpy(s+1, s); //应返回hhello,但实际会报错,因为dst与src重叠了,把'\0'覆盖了

所谓重叠,就是src未处理的部分已经被dst给覆盖了,只有一种情况:src<=dst<=src+strlen(src)

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

char * strcpy(char *dst,const char *src)

{

assert(dst!= NULL && src !=NULL);char *ret =dst;

my_memcpy(dst, src, strlen(src)+1);returnret;

}

my_memcpy的实现如下

char *my_memcpy(char *dst, const char* src, intcnt)

{

assert(dst!= NULL && src !=NULL);char *ret =dst;if (dst >= src && dst <= src+cnt-1) //内存重叠,从高地址开始复制

{

dst= dst+cnt-1;

src= src+cnt-1;while (cnt--)*dst-- = *src--;

}else //正常情况,从低地址开始复制

{while (cnt--)*dst++ = *src++;

}returnret;

}

java实现strcpy的函数原型_strcpy函数的实现相关推荐

  1. c语言scarf函数原型,scanf 函数原型.doc

    scanf 函数原型.doc scanf 函数原型 scanf 函数原型 int scanf( const char *format, ... ); scanf()函数是格式化输入函数,它从标准输入设 ...

  2. C++: 函数重载(c++函数原型、函数重载要素)

    1.c++函数原型 c++函数原型有3部分构成:返回值.函数名称.形参 c语言函数原型只与函数名有关 2.函数重载三要素 函数重载是c++中多态中静多态实现方法之一. 多态:静态多态(函数重载.泛型编 ...

  3. 【Kotlin】apply 内联扩展函数 ( apply 函数原型 | apply 函数示例 | Kotlin 调用 Java API )

    文章目录 I . 内联扩展函数 apply II . Kotlin 调用 Java API III . apply 内联扩展函数示例 ( 调用 Java API 处理图像 ) I . 内联扩展函数 a ...

  4. 函数声明(函数原型)的一些关键技巧

    当编译器遇到一个函数调用时,它产生代码传递参数并调用这个函数,而且接收该函数返回的值(如果有的话).但编译器是如何知道该函数期望接受的是什么类型和多少数量的参数呢?如何知道函数返回值的类型呢? 如果没 ...

  5. 函数定义、函数声明、函数原型

    函数定义.函数声明.函数原型:变量声明.变量定义:类型声明.类型定义 1.函数定义.函数声明.函数原型 2.变量声明.变量定义 3.类型声明.类型定义 1.函数定义.函数声明.函数原型 函数声明中不但 ...

  6. 【Android 逆向】ptrace 函数 ( C 标准库 ptrace 函数简介 | ptrace 函数真实作用 )

    文章目录 一.C 标准库 ptrace 函数简介 二.ptrace 函数真实作用 一.C 标准库 ptrace 函数简介 ptrace 函数 : 在 C 标准库 中有一个 ptrace 函数 , 该函 ...

  7. linux C函数之access函数的用法

    1.函数功能: 检查调用进程是否可以对指定的文件执行某种操作. 2.函数原型: 1)函数头文件 [cpp] view plain copy #include <stdio.h> #incl ...

  8. C++:函数重载:函数重载深入解析

    重载定义: 在 C++中,我们把具备相同功能的函数整合都一个函数上,而不必去写好多个函数名不同 的函数,这就 叫函数重载. 实作举例 比如我们要编写一个函数求一个数的 绝对值(但是整数,浮点型数,双精 ...

  9. 信号的用法,signal函数、sigaction函数及信号集(sigemptyset,sigaddset)操作函数

    信号是与一定的进程相联系的.也就是说,一个进程可以决定在进程中对哪些信号进行什 么样的处理.例如,一个进程可以忽略某些信号而只处理其他一些信号:另外,一个进程还可以选择如何处理信号.总之,这些总与特定 ...

最新文章

  1. java juel表达式_activiti 自定义函数解析juel表达式
  2. 科大星云诗社动态20210416
  3. linux vim配置缩减,让VIM更好的工作——VIM基本配置
  4. python with关键字_python with关键字学习
  5. UOS U盘已经复制成功,有时卡死
  6. [转]BAT 批处理脚本 教程
  7. 抖音视频什么时候投放dou+最好,dou+投放实战总结:国仁网络资讯
  8. TVB十大女星比美十大名花
  9. 文件岛 服务器大陆,重回文件岛《究极数码暴龙》奇遇系统解析
  10. 阿里云服务器+微信公众号配置(Token验证不通过)
  11. 嵌入式100题(81):波特率是什么,为什么双方波特率要相同,高低波特率有什么区别;...
  12. mencoder 报错处理
  13. 不驰于空想,不骛于虚声
  14. 1到50中7的倍数的数值之和
  15. 电商云仓储到底是什么?
  16. 专科云计算的出路在哪里?
  17. Jenkins 用户角色及权限管理
  18. wave6000可以c语言编程吗,WAVE6000使用教程初步.doc
  19. 简约商务报告PPT模板
  20. 【调剂】长春工业大学2020年硕士研究生招生预调剂公告

热门文章

  1. 序列化: 一个老家伙的咸鱼翻身(Java对象、XML、JSON、反序列化)
  2. 我的博客网站开发1——博客首页设计
  3. api接口通达信系统怎样开发量化回测及K线的显示买卖点程序?
  4. 介绍的比较全面中国人最容易懂的paxos
  5. ZZULIOJ21级新生周赛(1)——命题人:朱会东老师
  6. 计算机在职博士好毕业么,在职博士和全日制博士含金量有区别吗
  7. 回首2016的坚持,迎接2017的美好
  8. PAT-1089 狼人杀-简单版
  9. PLSQL ORA-00904 标识符无效
  10. DM368开发 -- 华为3G/4G模块移植