这两个函数他们主要有2点不同:
①:strcpy仅仅只能复制字符串,但是memcpy却可以复制所有的类型。因为memcpy()函数执行的内存copy这个操作。也就是把source处的内存数据复制到destination内存处。
②:strcpy复制字符串的时候,什么时候结束是依赖于source处字符串的’\0’来决定的。但是memcpy复制的时候,复制多少个字节是采用第三个参数来决定的。那么此时如果采用memcpy来复制字符串的话,我们一定要记得将’\0’给复制过去,不然就会出现一些问题。而strcpy在复制的时候,会自动将dst最后面加上一个’\0’,所以不需要考虑这个问题。
int main()
{
char data[256];
memcpy(data, "12345", 5);
cout << data << endl;
strcpy(data, "6789");
cout << data << endl;
return 0;
}
这个程序数据结果就是:
因为我们data这个数组没有初始化,而采用memcpy复制的时候,又没有把’\0’给复制过去,所以导致了打印处了烫烫烫…
解决方法又两个:
a.将data初始化,可以先将其的内存全部复制为‘\0’
memset(data, 0,256);
b.在memcpy的时候将’"12345"的’\0’给复制过去。
memcpy(data, "12345", 6);
既然我们都提到了memcpy,我需要提出就是:我们采用printf("%s",data);或者是cout<<data<<endl;的时候,到底是如何处理这个指针的。例如下面这个代码:
int main()
{
char *data = (char*)malloc(sizeof(char) * 10);
if (!data)
{
cout << "内存分配失败" << endl;
return -1;
}
memset(data, 0, sizeof(char) * 10);
memcpy(data, "1234", 5);
data = (char*)"hello";
cout << "没有调用memcpy之前:"<<data << endl;
//memcpy(data, "12", 3);
//printf("%s", data);
//cout << "调用memcpy之后:" << data << endl;
return 0;
}
在我的一次调试结果中:
a.在执行了char data = (char)malloc(sizeof(char) * 10);之后,data的值就是:0x00BA1EF8。这个代表的意思就是现在data就是指向内存为0x00BA1EF8 的开始的10个字节。我们现在来看看内存为0x00BA1EF8处的数据是什么:
和我们预想的差不多,因为这块内存是没有初始化的,所以0x00BA1EF8位置存放的就是cd cd…因为在vs2017下,没有初始化的数据差不多都是这个。
b.在执行了memset(data, 0, sizeof(char) * 10);之后,内存0x00BA1EF8开始的10个字节应该存放的都是0。我们从内存中看看:
c.然后我们执行了memcpy(data, “1234”, 5);这个语句意思就是:把"12345\0"这个一共5个字符复制到data所指的这块内存中的。而不是说:把"12345\0"这个5个字符的数据来替代data的值0x00BA1EF8。即:执行完memcpy(data, “1234”, 5);后,data的值还是0x00BA1EF8,只是内存0x00BA1EF8开始的5个字节就从00000变成了1234\0
d.然后执行cout<<data<<endl;我们做的是:将data的值也就是0x00BA1EF8位置的数据打印出来,直到遇到\0;我们并不是把data的值打印出来,而是把data值所指向的数据打印出来。
e.但是data = (char*)“hello”;这条语句并不是将内存0x00BA1EF8的数据改为"hello",而是说将data的值改变为执指向文字常量区的一块数据。也就是说,现在data的值不是0x00BA1EF8了,而是0x00474dfc,而内存为0x00474dfc的位置上,存放的就是’'hello\0"。
此时的内存四区图就是这样子的:
也就是说:内存0x0133FEB4存放的是0x00BA1EF8,而内存0x00BA1EF8存放的是“hello\0”
f.但是执行完data = (char*)“hello”;之后,紧接着执行memcpy(data, “12”, 3);是会报错的。因为我上面c步中就说明了memcpy的操作,而这里memcpy(data, “12”, 3);就是要把"12\0"这个字符串复制到data所指向的内存区域。但是现在data指向是一个文字常量区,是不允许改变的。所以程序此时会报错。
总结一下:我就是想要表达:我们在执行
printf("%s",data);
cout<<data<<endl;
这两条语句的时候,我们是会打印data的值所指向的内存的区域的数据,而是不是打印data内存的值。