/***
str_copy.c
***/
#include<stdio.h> void copy_str21(char *from, char *to)
{
for(; *from != '\0'; from++,to++)
{
*to = *from;
}
*to = '\0'; return;
} int main()
{
char *from = "abcd";
char buf2[];
copy_str21(from,buf2);
printf("buf2:%s\n",buf2);
return ;
}

程序内存四区分析:

char *from = "abcd";  操作系统在在常量区分配一个内存存放”abcd”,在栈区定义分配一块内存,取名位from,from指向的这块内存存储“abcd”的首地址。

char buf2[100]; 操作系统在栈区分配一块内存,开头与栈区增长方向相反,大小为100个字节

copy_str21(from,buf2);        程序进入到该函数中

void copy_str21(char *from, char *to)        操作系统在继续在栈中分配两块内存,分别用to和from指向这两块内存。并且把mian函数中的from,to地址首部存放在该函数中分配到from,to指针指向的内存

for(; *from != '\0'; from++,to++)

{

*to = *from;

}

copy_str21函数中from指针存储的地址是常量“abcd”的首地址,to指针存储的是mian函数中buf2数组的首地址。然后把from指针不断后移区内容赋值给to指针不断后移所指向的内存空间。

*to = '\0';      由于buf2没有进行初始化,所以最后要在结束的时候把最后面的内存赋值0,作为C语言字符串的结尾。

然后程序返回,copy_str21栈地址回收,主函数打印buf2字符数组。

copy函数技术演练

/***
str_copy.c
***/
#include<stdio.h> void copy_str21(char *from, char *to)
{
for(; *from != '\0'; from++,to++)
{
*to = *from;
}
*to = '\0'; return;
} void copy_str22(char *from,char *to)
{
for(;*from != '\0';)
{
*to++ = *from++;
}
*to = '\0';
return ;
} void copy_str23(char *from,char *to)
{
while( (*to = *from) != '\0')
{
from++;
to++;
}
} void copy_str24(char *from,char *to)
{
while((*to++ = *from++) != '\0')
{
;
}
} void copy_str25(char *from,char *to)
{
while( (*to++ = *from++) );
}
int main()
{
char *from = "abcd";
char buf1[];
char buf2[];
char buf3[];
char buf4[];
char buf5[]; copy_str21(from,buf1);
printf("buf1:%s\n",buf1);
copy_str22(from,buf2);
printf("buf2:%s\n",buf2);
copy_str23(from,buf3);
printf("buf3:%s\n",buf3);
copy_str24(from,buf4);
printf("buf4:%s\n",buf4);
copy_str25(from,buf5);
printf("buf5:%s\n",buf5);
return ;
}

运行结果:

exbot@ubuntu:~/shareWin/CAndC++/20190924$ gcc strcopy.c -o strcopy -g

exbot@ubuntu:~/shareWin/CAndC++/20190924$ ./strcopy

buf1:abcd

buf2:abcd

buf3:abcd

buf4:abcd

buf5:abcd

/***
copy_str.c
***/
#include<stdio.h> int copy_str26_good(char *from,char *to)
{
if(from == NULL || to == NULL)
{
return -;
} while(*to++ = *from++); return ;
} int copy_str27_verygood(char *from,char *to)
{
if(from == NULL || to == NULL)
{
return -;
} char *tempfrom = from;
char *tempto = to;
while(*tempto++ = *tempfrom++); return ;
}
int main()
{
int ret = ;
char *from = "abcd";
char buf[];
char buf1[]; //传进来的指针如果被初始化指向null的话,是不需要被修改的
//因为null和0是操作系统内部一块无法访问和修改的地址空间存储的
//所以提前对传进来的指针进行判断,如果为null,则返回错误
ret = copy_str26_good(from,buf);
if(- == ret)
{
printf("ponit p or buf is null\n");
}
else
{
printf("copy success buf = %s\n",buf);
} //不要轻易改变形参的值,要引入一个辅助的变量指针,把形参接过来
ret = copy_str27_verygood(from,buf1);
if(- == ret)
{
printf("ponit p or buf is null\n");
}
else
{
printf("copy success buf1 = %s\n",buf1);
}
return ;
}

运行结果:

exbot@ubuntu:~/shareWin/CAndC++/20190924$ ./copy_str

copy success buf = abcd

copy success buf1 = abcd

copy()函数技术推演的更多相关文章

  1. C语言 数组做函数参数退化为指针的技术推演

    //数组做函数参数退化为指针的技术推演 #include<stdio.h> #include<stdlib.h> #include<string.h> //一维数组 ...

  2. Redux 实现过程的推演

    这是一篇浅入浅出的 Redux 实现过程的推演笔记!正常来说应该是要从源码下手开始解析,这里是逆向推演,假如有需求是要这么一个东西,那么该如何从零开始实现? 通过该笔记,更多的是希望自己能够多熟悉从无 ...

  3. 从匿名方法到 Lambda 表达式的推演过程

    Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数. 通过使用 lambda 表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数. 以上是msdn官网对Lambda 表达式 ...

  4. javascript基础修炼(4)——UMD规范的代码推演

    javascript基础修炼(4)--UMD规范的代码推演 1. UMD规范 地址:https://github.com/umdjs/umd UMD规范,就是所有规范里长得最丑的那个,没有之一!!!它 ...

  5. Excel催化剂开源第11波-动态数组函数技术开源及要点讲述

    在Excel催化剂中,大量的自定义函数使用了动态数组函数效果,虽然不是原生的Excel365版效果(听说Excel2019版取消了支持动态数组函数,还没求证到位,Excel365是可以用,但也仅限于部 ...

  6. 从下往上看--新皮层资料的读后感 第三部分 70年前的逆向推演- 从NN到ANN

    第三部分 NN-ANN 70年前的逆向推演 从这部分开始,调整一下视角主要学习神经网络算法,将其与生物神经网络进行横向的比较,以窥探一二. 现在基于NN的AI应用几乎是满地都是,效果也不错,这种貌似神 ...

  7. php不使用copy()函数复制文件的方法

    本文实例讲述了php不使用copy()函数复制文件的方法.分享给大家供大家参考.具体如下:下面的代码不使用php内置的copy函数,直接通过文件读取写入的操作方式复制文件 <?php funct ...

  8. 利用copy函数简单快速输出/保存vector向量容器中的数据

    如果要输出vector中的数据我们可以通过循环语句输出,更加简便的方法是利用copy函数直接输出,例子: #include "stdafx.h" #include <iost ...

  9. 使用copy函数完成数据库迁移

    最近在该一个迁移工具的迁移方式,从ora8迁移到postgresql使用原来的插入迁移速度太慢了,老板说让使用缓存迁移,即使用postgresql的copy函数,因此去pg官网查阅了相关资料,我们需要 ...

随机推荐

  1. C#程序结构(学习笔记01)

    C#程序结构 [原文参考官方教程] https://docs.microsoft.com/zh-cn/dotnet/csharp/tour-of-csharp/program-structure C# ...

  2. winform实现图片的滑动效果

    使用winform实现图片的滑动效果(类似网站首页图片滑动切换效果),结果实现了,但是效果其实不是很理想.也许有更好的方法.         Timer timerSlide = null; //当前 ...

  3. MySQL事务和事务隔离级别

    1.概述 事务就是对数据库数据进行更改(包括insert.update.delete等)操作的一个执行单元,通常有一条或多条更改语句组成.在同一个事务中的更改操作要么同时成功,要么同时失败. 事务具有 ...

  4. VS2017 配置 boost_1_70

    1. 下载与安装 1.1 安装方法1 (1) 下载 https://www.boost.org/ 或者使用 https://sourceforge.net/projects/boost/files/b ...

  5. 【转载】 C#中List集合使用First()方法获取第一个元素

    在C#的List集合操作过程中,如果要获取List集合中的第一个元素对象,则一般会先通过获取到list[0]这种方式来获取第一个元素.其实在List集合中提供了获取最后一个元素的First()方法,调 ...

  6. 部署---Apache服务器安装SSL证书

    在云服务器的证书控制台下载Apache版本证书,下载到本地的是一个压缩文件. 解压后里面包含: _public.crt文件是证书文件, _chain.crt是证书链(中间证书)文件, .key文件是证 ...

  7. robot framework笔记(三):扩展SeleniumLibrary库 (自定义关键字)

    (一)自定义和浏览器相关的关键字 以下代码GitHub 版本库地址: https://github.com/blairwind/blog_rf SeleniumLibrary的扩展文档中提供了3种增加 ...

  8. Python学习日记(二十五) 接口类、抽象类、多态

    接口类 继承有两种用途:继承基类的方法,并且做出自己的改变或扩展(代码重用)和声明某个子类兼容于某基类,定义一个接口类interface,接口类中定义了一些接口名(就是函数名)且并未实现接口的功能,子 ...

  9. Crypto模块中的签名算法

    因为支付宝当中需要自行实现签名,所以就用到了SHA265和RSA2,将拼接好的信息用私钥进行签名,并进行Base64编码,然后解密就用支付宝回传给用户的公钥解密就ok了,所以我就使用Crypto模块, ...

  10. TP5框架模块绑定二级域名

    application\config.php 修改 url_domain_deploy 为 true 'url_domain_deploy' => true application\route. ...