strcpy、memcpy、memmove

今天看了下strcpy、memcpy、memmove的用法功能和他们的区别,以及在网上看到一些解答,在此做点总结:

1、strcpy  、memcpy、memmove 函数原型及功能

      strcpy的函数原型是:char* strcpy(char* dest, const char* src);

      strcpy提供了字符串的复制。即strcpy只用于字符串复制,并且它不仅复制字符串内容外,还会复制字符串的结束符。

      memcpy的函数原型是:void *memcpy(void *dest,  const char* src,  size_t count);

    memcpy只提供一般的内存复制,即memcpy对于需要复制的内容没有限制,因此用途更广。

    memmove的函数原型是:id *memmove(void *dest,const void *src,int n)


    memmove该函数和前面函数的区别是当src和desc有重复区域时,则会先将desc向后移,然后再进行拷贝操作.


2、strcpy  、memcpy、memmove 函数实现

    1)strcpy的实现:(未考虑内存重叠)

     

<span style="color:#000099;">char *my_strcpy(char *dst,const char *src)  
{  
    assert(dst != NULL);  
    assert(src != NULL);  
    char *ret = dst;  
    while((* dst++ = * src++) != '\0')   
        ;  
    return ret;  
}  </span>
    

如果注意到:

   1,检查指针有效性;

   2,返回目的指针des;

   3,源字符串的末尾 '\0' 需要拷贝。

   写出上面实现函数就不在话下。

   然而这样的实现没有考虑拷贝时内存重叠的情况,下面的测试用例就能使调用my_strcp函数的程序崩溃:

   char str[10]="abc"

my_strcpy(str+1,str);


然而调用系统的strcpy函数程序正常运行,打印str结果为“aabc”!可见系统strcpy函数的实现不是这样的。

    strcpy的正确实现应为:

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

{

assert(dst != NULL);

assert(src != NULL);

char *ret = dst;

memcpy(dst,src,strlen(src)+1);

return ret;

}

memcpy函数实现时考虑到了内存重叠的情况,可以完成指定大小的内存拷贝。

 2)memcpy(考虑内存重叠)

    

void * My_memcpy(void *dst,const void *src,unsigned int count) 
{
	assert(dst);  
	assert(src);  
	void * ret = dst;  
	//源地址和目的地址不重叠,低字节向高字节拷贝  
	if (dst <= src || (char *)dst >= ((char *)src + count))
	{  
		while(count--)  
		{  
			*(char *)dst = *(char *)src;  
			dst = (char *)dst + 1;  
			src = (char *)src + 1;  
		}  
	}  
	else  //源地址和目的地址重叠,高字节向低字节拷贝  
	{   
		dst = (char *)dst + count - 1;  
		src = (char *)src + count - 1;   
		while(count--)   
		{  
			*(char *)dst = *(char *)src;  
			dst = (char *)dst - 1;  
			src = (char *)src - 1;  
		}  
    }  
    return ret;
}
 3)memmove (考虑内存重叠)

      

<span style="color:#3333ff;">void *memmove(void *dst,const void *src,int n)
{
     char *dp = (char *)dst;
     char *sp = (char *)src; 
     assert((src!=0)&&(dst!=0)&&(n>0));//not null 
     //非重叠 
      //dp < sp 
     //dp > (sp+n)
     if(sp>dp||(sp+n)<dp)
     { 
         while(n--) 
             *(dp++) = *(sp++);
         *dp = '\0';
     }
     else if(sp<dp)//重叠 (此时条件 sp<dp<(sp+n))如果sp==dp则快速的返回
     {//反向拷贝  
          sp += n;    //helloworld
         dp += n; 
         *dp = '\0'; 
         while(n--)
            *(--dp) = *(--sp); 
     }
     return dst;
}</span>
4、 strcpy    、memcpy、memmove的区别:   

     strcpy 和 memcpy主要有以下三方面的区别:

     1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符串、整型、结构体、类等。

     2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符串的结束符"\0”才结束,所以容易溢出。memcpy则是根据第3个参数决定复制的长度。

     3、用途不同。通常在复制字符串时用strcpy,而需要复制其它类型的数据是用memcpy

 

     memcpy 和 memmove 都是C语言中的库函数,在库函数 string.h中,其原型相似,它们都是从src所指向的内存中复制count个字节到dest所指内存中。并返回dest的值。

当源内存区域 和 目标内存区域无交叉重叠时,两者的结果是一样的,但如果有交叉呢?

memcpy是从src的其实部分开始复制,所以虽然第一种情况下没有问题,但如果遇到第二种情况,则会发生错误,交叉部分的src内容就会被覆盖掉了。


5、memmove的处理措施:

   (1)当源内存的首地址等于目标内存的首地址时,不进行任何拷贝


   (2)当源内存的首地址大于目标内存的首地址时,实行正向拷贝


   (3)当源内存的首地址小于目标内存的首地址时,实行反向拷贝


编程老手们:有什么遗漏的,请留下你们的想法和补充,谢谢。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. atof(): 将字符串转换为double类型的值。 例如: ```c++ char str[] = "3.14"; double num = atof(str); printf("%f", num); ``` 结果为:3.140000 2. atoi(): 将字符串转换为int类型的值。 例如: ```c++ char str[] = "1234"; int num = atoi(str); printf("%d", num); ``` 结果为:1234 3. atol(): 将字符串转换为long类型的值。 例如: ```c++ char str[] = "1234567"; long num = atol(str); printf("%ld", num); ``` 结果为:1234567 4. strtod(): 类似于atof(),将字符串转换为double类型的值。 例如: ```c++ char str[] = "3.14"; double num = strtod(str, NULL); printf("%f", num); ``` 结果为:3.140000 5. strtol(): 将字符串转换为long类型的值,同时支持指定转换的基数(例如10进制、16进制等)和错误检查。 例如: ```c++ char str[] = "0110"; long num = strtol(str, NULL, 2); printf("%ld", num); ``` 结果为:6 6. strtoul(): 类似于strtol(),不过返回的是无符号的long类型。 例如: ```c++ char str[] = "0xA"; unsigned long num = strtoul(str, NULL, 16); printf("%lu", num); ``` 结果为:10 7. memset(): 将一段内存区域设置为指定的值。 例如: ```c++ char str[10]; memset(str, 'a', sizeof(str)); printf("%s", str); ``` 结果为:aaaaaaa 8. memcpy(): 将一段内存区域的内容复制到另一段内存区域。 例如: ```c++ char src[] = "hello"; char dst[10]; memcpy(dst, src, sizeof(src)); printf("%s", dst); ``` 结果为:hello 9. memmove(): 和memcpy()类似,但是保证在有重叠的情况下会正确工作。 例如: ```c++ char str[] = "hello"; memmove(str + 2, str, 3); printf("%s", str); ``` 结果为:hehlo 10. memcmp(): 比较两段内存区域的内容是否相等。 例如: ```c++ char str1[] = "hello"; char str2[] = "Hello"; int result = memcmp(str1, str2, 5); printf("%d", result); ``` 结果为:32(h和H的ASCII码差值) 11. memchr(): 在一段内存区域中搜索指定的字符,并返回指向该字符的指针。 例如: ```c++ char str[] = "hello"; char* ptr = (char*)memchr(str, 'l', 5); printf("%s", ptr); ``` 结果为:ll 12. strcpy(): 将一个字符串复制到另一个字符串。 例如: ```c++ char src[] = "hello"; char dst[10]; strcpy(dst, src); printf("%s", dst); ``` 结果为:hello 13. strncpy(): 类似于strcpy(),不过只会复制指定长度的字符。 例如: ```c++ char src[] = "hello"; char dst[10]; strncpy(dst, src, 3); dst[3] = '\0'; printf("%s", dst); ``` 结果为:hel 14. strcat(): 将一个字符串附加到另一个字符串的末尾。 例如: ```c++ char str1[] = "hello"; char str2[] = "world"; strcat(str1, str2); printf("%s", str1); ``` 结果为:helloworld 15. strncat(): 类似于strcat(),不过只会附加指定长度的字符。 例如: ```c++ char str1[] = "hello"; char str2[] = "world"; strncat(str1, str2, 3); printf("%s", str1); ``` 结果为:helloworld 16. strcmp(): 比较两个字符串是否相等。 例如: ```c++ char str1[] = "hello"; char str2[] = "world"; int result = strcmp(str1, str2); printf("%d", result); ``` 结果为:-15 17. strncmp(): 类似于strcmp(),不过只会比较指定长度的字符。 例如: ```c++ char str1[] = "hello"; char str2[] = "world"; int result = strncmp(str1, str2, 3); printf("%d", result); ``` 结果为:0 18. strchr(): 在一个字符串中搜索指定的字符,并返回指向该字符的指针。 例如: ```c++ char str[] = "hello"; char* ptr = strchr(str, 'l'); printf("%s", ptr); ``` 结果为:llo 19. strrchr(): 类似于strchr(),不过会从字符串的末尾开始搜索。 例如: ```c++ char str[] = "hello"; char* ptr = strrchr(str, 'l'); printf("%s", ptr); ``` 结果为:lo 20. strstr(): 在一个字符串中搜索指定的子字符串,并返回指向该子字符串的指针。 例如: ```c++ char str[] = "hello world"; char* ptr = strstr(str, "world"); printf("%s", ptr); ``` 结果为:world
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值