memmove与memcpy用法区别
memmove函数
#include <string.h>
void *memmove(void *dest, const void *src, size_t n);
功能:由src指向地址为起始地址的连续n个字节的数据复制到以dest指向地址为起始地址的空间内。
返回:memmove()函数返回指向dest的指针。
注意: 在使用的过程中,发现一个问题,如果源地址中的拷贝字节数 n < strlen(dest)
,即源地址拷贝字节小于目的地址数据,当源数据当中有\0
时,则将目的地址替换的位置后面全部清空。
#include <string.h>
void *memcpy(void *dest, const void *src, size_t n);
功能: memcpy()函数从src内存中拷贝n个字节到dest内存区域,但是源和目的的内存区域不能重叠。
返回:memcpy()函数返回指向dest的指针。
图片来源与网络:
在下图的情况下进行拷贝,两个函数无差别。
但如果如下图情况,出现重叠部分,memcpy()源地址拷贝到目的地址时,可能会把拷贝到目的地址的数据又放回到源地址,这样肯定不是我们想要的结果。而memmove()则不会出错。
举个例子:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
float buf3 = 23.33;
int i;
//char fb[20] = {0x32, 0x33, 0x2e, 0x33, 0x33}; //ASCii码当中的十六进制表示
char fb1[20] = "123456789";
char fb2[20] = "123456789";
char fb3[20] = "123456789";
char fb4[20] = "123456789";
//有重叠时才能体现memmove与memcpy的区别
memmove(&fb1[3], fb1, 6);
printf("%s\n", fb1);
memcpy(&fb2[3], fb2, 6);
printf("%s\n", fb2);
//未重叠时memmove与memcpy功能无差别
memmove(&fb3[0], &fb3[3], 5);
printf("%s\n", fb3);
memcpy(fb4, &fb4[3], 5);
printf("%s\n", fb4);
return 0;
运行结果如下:
123123456 //memmove
123123423 //memcpy
456786789
456786789
拷贝时,有地址重叠则memcpy拷贝出错。
无重叠它们功能无差别。
另外再题下关于strlen使用的注意:
自己遇到了坑,老是提示段错误
,发现计算长度已经越界了。
char * str1 = "abc";
char * str2 = "ab\0c";
char * str3 = "ab\\0c";
char * str4 = "abc0c";
char arr0[5] = {'1', '2', '3', '4', '5'};
char arr1[5] = {'1', '2', '3', '4', '\0'};
char arr2[5] = {'1', '2', '3', '4', 0};
char arr3[5] = {'0', '0', '0'};
char arr4[5] = {0, 'a', 'b'};
char arr5[5] = {'a', '\0', 'b'};
char arr6[5] = {'a', 0, 'b'};
进行strlen计算时的结果如下:
3 2 5 5 未知 4 4 3 0 1 1
通过这个可以知道:
- strlen遇到
\0
就直接结束,因为十进制0的ASCII码是\0
- 字符串会默认在末尾加上
\0
,所以计算时不会出现错误,得到的是真实数据; - 计算字符时,因为字符数组当中没有
\0
的话,不会结束,这时已经超出数组,计算的长度就无法确定了。