strcpy和memcpy函数是项目中常常常使用到的函数。可能因为使用不当造成数据错误或引发程序段错误等等。以下我们就来细细分析这两个很重要的函数。
/*File : strcpy_memcpy.c
*Auth : sjin
*Date : 20141019
*Mail : 413977143@qq.com
*/
/* 主要针对strcpy及与memcpy函数的差别
* strcpy 函数在使用过程中的注意事项等等。在面试时及平时
* 代码编写中常常遇到的问题。
*/
#include <stdio.h>
/*strcpy函数提供了字符串的复制,即仅仅用于字符串的复制。而且它不仅复制
* 字符串内容之外。还会复制字符串的结束符。
遇到结束符则停止复制 *函数原型char *strcpy(char *dest,const char *src) */ char * mystrcpy(char *dest,const char *src) { if((dest == NULL) || (src == NULL)){ return NULL; } char *strdest = dest; //保存目标字符串的首地址 while((*strdest ++ = *src++) != '\0'); return dest; } /*memcpy函数提供了一般内存的复制,即对须要复制的内容没有限制 * 函数原型 void *memcpy(void * dest,const void * src,size_t count); * * 对于地址重叠情况 。该函数的是没有定义的 */ void * mymemcpy1(void *dest,const void *src,size_t count) { /*未考虑内存重叠情况*/ if((dest == NULL) || (src == NULL)){ return NULL; } char *strdest = (char *)dest; char *strsrc = (char *)src; while(count-- > 0){ *strdest++ = *strsrc++; } return dest; } void * mymemcpy2(void *dest,const void *src,size_t count) { char *strdest = NULL; char *strsrc = NULL; /*内存重叠情况*/ if((dest == NULL) || (src == NULL)){ return NULL; } if((src < dest) && (((char *)src + count) > (char *)dest)){ strdest = (char *)dest + count - 1; strsrc = (char *)src + count - 1; while(count--){ *strdest-- = *strsrc--; } }else{ strdest = (char *)dest; strsrc = (char *)src; while(count-- > 0){ *strdest++ = *strsrc++; } } return dest; } /*strcpy 与memcpy差别: *1 复制的内容不同。strcpy 仅仅能复制字符串。而memcpy复制随意内容。
*2 复制的方法不同,strcpy不须要指定长度,它遇到字符串结尾符结束。 * 所以easy溢出。
memcpy则是依据第三參数聚丁复制的长度 *3 用途不同。通常在复制字符串时用strcpy,而须要复制其它数据类型数据时则一般用memcpy *4 内存重叠时,strcpy会出现段错误。而memcpy不会 */ int main() { char buf[16] = "abcdefghijk"; char buf1[16] = "abcdefghijk"; char buf2[16] = "abcdefghijk"; char buf3[16] = "abcdefghijk"; //strcpy(buf+2,buf); ###程序崩溃,段错误 memcpy(buf + 2,buf,5); memmove(buf1+2,buf1,5); mymemcpy1(buf2 + 2,buf2,5); mymemcpy2(buf3 + 2,buf3,5); printf(" end of memcpy(buf +2,buf,5), buf is :%s\n",buf); printf(" end of memmove(buf1 +2,buf1,5), buf1 is :%s\n",buf1); printf(" end of mymemcpy1(buf2 +2,buf2,5), buf2 is :%s\n",buf2); printf(" end of mymemcpy2(buf3 +2,buf3,5), buf3 is :%s\n",buf3); return 0; }
输出结果:
end of memcpy(buf +2,buf,5), buf is :ababcdehijk
end of memmove(buf1 +2,buf1,5), buf1 is :ababcdehijk
end of mymemcpy1(buf2 +2,buf2,5), buf2 is :abababahijk
end of mymemcpy2(buf3 +2,buf3,5), buf3 is :ababcdehijk
关于内存重叠,对我来说是个新名词。所谓的内存重叠个人理解就是拷贝的目的地址在源地址的范围内。
通过上面的打印结果我们能够看到。
memcpy函数,本身是支持内存重叠的(有些资料或博客中说不支持的,有待考证)。mymemcpy1函数是不支持的,而mymemcpy2函数是支持的,所以说。mymemcpy2才是memcpy的详细实现。
关于strcpy并不支持内存重叠,编译过程中会出现段错误的。因此我总结了strcpy和memcpy函数的差别,有以下4条:
1 复制的内容不同,strcpy 仅仅能复制字符串,而memcpy复制随意内容。
2 复制的方法不同,strcpy不须要指定长度,它遇到字符串结尾符结束。
所以easy溢出。
memcpy则是依据第三參数聚丁复制的长度。
3 用途不同。
通常在复制字符串时用strcpy。而须要复制其它数据类型数据时则一般用memcpy。
4 内存重叠时。strcpy会出现段错误,而memcpy不会。
关于strcpy函数,再看以下的代码
/*File : strcpy.c
*Auth : sjin
*Date : 20141019
*Mail : 413977143@qq.com
*/
/*关于strcpy的一些重要的面试题
* */
#include <stdio.h>
#include <string.h>
int main()
{
char str[10] = {'\0'};
char str1[10] = {'\0'};
int i = 0;
//for(i = 0; i < 10; i++){
//上面的将会出现段错误。
未考虑字符串的结束符 for(i = 0; i < 9; i++){ str1[i] = 'a'; } strcpy(str,str1); printf("str is :%s\n",str); return 0; }