strcpy源码实现

本文探讨了strcpy与memcpy的区别,重点分析了strcpy的源码实现,详细解释了while循环中的赋值和指针递增操作,以及该实现如何避免可能导致的bug。通过深入解析,读者能更好地理解strcpy的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

strcpy与memcpy区别:
1、复制的内容不同。strcpy只能复制字符串,包括结束符,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy

 

以下情况使用memcpy会导致bug出现:

char recvBuffer[20] = {0};
memcpy(recvBuffer, "1.00", sizeof(recvBuffer)); //拷贝长度超过了"1.00"的长度,有可能会拷贝其它内容到recvBuffer中
printf("recvBuffer=%s\n",recvBuffer);  //多线程、多进程环境下,打印内容可能会有乱码,当然前5个字符是"1.00"加上'\0'

以上打印内容中,前5个字符是确定的,但是从第6个字符到第20个字符的内容是不确定的。

所以,这种情况最好使用strcpy:

strcpy(recvBuffer, "1.00");

或者:

memcpy(recvBuffer, "1.00", strlen("1.00"));  //strlen("1.00")=4,不包括结束字符

 

strcpy实现:

char *strcpy_de(char *dest, const char *src){
    if(dest == NULL && src == NULL)
        return NULL;
    char *tempDest = dest;
    while((*tempDest++ = *src++) != '\0');//赋值后,先判断*tempDest的值是否是'\0',再自加1
    return dest;
}

while((*strDest++ = *strSrc++) != '\0'); 的分析:(参考 https://blog.csdn.net/qiqisunshine/article/details/77185019

1. 很明显,上面的表达式是一个组合表达式。组合表达式由子表达式组成,子表达式又可能是组合表达式,这样就形成了一个树状的数据结构。对表达式的评估就类似于对树结点的遍历。首先我们应该注意到"()"操作符,它具有最高的优先级,所以从整体来看,整个表达式应该是个"!="操作。"!="左边又是一个组合表达式,而右边是一个常量"\0',很明显下面的工作就是评估(*strDest++=*strSrc++)。

2.在这一步,我们要对表达式(*strDest++=*strSrc++)进行评估。由于赋值表达式具有较低的优先级,所以表达式 又可以写成:(*strDest++) = (*strSrc++),所以整个表达式是个"="操作,"="左边又是一个组合表达式,右边也是一个组合表达式,这里就需要从关联性来判断左边还是右边也被评估。由于"="的关联性是从右到左,所以(*strSrc++)先被评估,(*strDest++)后被评估。

2.1 在这一步,我们要对表达式(*strSrc++)进行评估。由于"++"的优先级大于"*",所以表达式又可以写成:*(strSrc++)。我们要先对表达式strSrc++进行评估,然后用表达式的值再去评估*(strSrc++)的值。对于表达式strSrc++,这里要需要注意区分变量的值和表达式的值。对于"后增1"表达式,表达式的值是变量strSrc的值,然后变量strSrc的值会"加1",也就是说表达式的值是strSrc变化前的值,而strSrc的值会发生变化。值得注意的是,我们知道strSrc的值会发生变化,但是我们却不知道strSrc的值发生变化的具体时间,这个变化具体的执行时间由编译器决定了,这就决定了任何依赖strSrc的表达式的值是不确定的,具体的值依赖编译器的实现。完成了对strSrc++的评估后,取值操作符就对表达式的值所对应的内存空间进行取值操作。

2.2 在这一步,我们要对表达式(*strDest++)进行评估。具体的评估的分析完全和2.1中的分析一致。

2.3 在这一步,我们要对表达式(*strDest++) = (*strSrc++)进行评估,这是个赋值表达式,将右表达式的值赋给左边表达式的值。值得注意的是,对于赋值表达式,表达式本身的值等于左边子表达式的值。

3.由于"!="表达式左边的子表达式的值已经被评估出来了,下面就执行"!="操作。"!="表达式的是一个布尔值。

 

通过以上深入的分析,我们知道这个表达式完成了以下多个功能:

  1.对于指针strDest, strSrc,将strSrc所指的内存空间的值赋给由strDest所指的内存空间。

  2.判断赋值后的strDest所指的内存空间的指是否等于0。

  3.对于指针strest,strSrc,他们的值分别加1,即指向下一个元素。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值